bashir milad
bashir milad

Reputation: 39

I've a problem when I use the Sleep?

why in my code, the TextView does not take except the last count. the result just is: counter= 4

int i =0;

while (i< 5) {
    try {
        Thread.sleep((i*1000));
        mText.setText("counter"+ i);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    // mText does not show
    mText.setText("counter= "+ i);
    i = i +1;
} 

Upvotes: 0

Views: 153

Answers (6)

David Heffernan
David Heffernan

Reputation: 612794

Generally, good solutions to problems with sleep() involve stopping using sleep(). Blocking the UI thread is always a very bad idea. It makes you application's UI non-responsive.

In your case you want an event to run every second. The correct way to implement that is with a timer.

Upvotes: 0

Snicolas
Snicolas

Reputation: 38168

Many answers here gave you all the information you need to achieve what you want but it may be difficult to understand.

I will propose you below a new way to achieve it, maybe easier. But I want to underline that you should understand what people wrote, my previuos post and the one from @LAS_VEGAS at least.

Here is something easy : use a handler.

add a data member like

Handler handler = new Handler();

then on click :

for (int i = 0; i < 5; i++}{
    handler.postDelayed( new Runnable() {
        public void run() {
            mText.setText("counter"+ i);
        }
    }, i * 1000 );  
}

I don't have access to my very own computer right now and fear this may not compile due to a non final variable used inside a annonymous inner class. So you could also try to build a named inner class like this in your main java class :

public class ButtonTimerThread implements Runnable
{
     privqte int i =0;

     public ButtonTimerThread( int i)
     {
           this.i = i;
     }//cons

     public void run()
     {
            mText.setText("counter"+ i);
     }//met
}//class

qnd then you click listener method would look like :

for (int i = 0; i < 5; i++}{
    handler.postDelayed( new ButtonTimerThread( i ), i * 1000 );  
}

As your handler will be created by the UI thread, it will be able to update UI. The handler offers the advantage to have a delay mechanism that doesn't block the UI thread that is reacting to your click action.

I hope this helps, Stéphane

Upvotes: 0

Caner
Caner

Reputation: 59148

You are blocking the UI thread when your app sleeps, so the screen is not redrawn, hence you don't see the text changes until your loop ends.

The UI thread

When an application is launched, the system creates a thread called "main" for the application. The main thread, also called the UI thread, is very important because it is in charge of dispatching the events to the appropriate widgets, including drawing events. It is also the thread where your application interacts with running components of the Android UI toolkit.

For instance, if you touch the a button on screen, the UI thread dispatches the touch event to the widget, which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies the widget to redraw itself.

This single-thread model can yield poor performance unless your application is implemented properly. Specifically, if everything is happening in a single thread, performing long operations such as network access or database queries on the UI thread will block the whole user interface. No event can be dispatched, including drawing events, while the long operation is underway. From the user's perspective, the application appears hung. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog.

If you want to see how bad this can look, write a simple application with a button that invokes Thread.sleep(2000) in its OnClickListener. The button will remain in its pressed state for about 2 seconds before going back to its normal state. When this happens, it is very easy for the user to perceive the application as slow.

To summarize, it's vital to the responsiveness of your application's UI to keep the UI thread unblocked. If you have long operations to perform, you should make sure to do them in extra threads (background or worker threads).

More info:
http://developer.android.com/resources/articles/painless-threading.html

That is the problem. And AsyncTask is (one) solution:

AsyncTask

AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread.

http://developer.android.com/reference/android/os/AsyncTask.html

Upvotes: 3

Glitch
Glitch

Reputation: 2785

Use a for loop (inside a non-UI thread):

for (int i = 0; i < 5; i++}{
    try {
        Thread.sleep((i*1000));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    runOnUIThread(new Runnable() {
        public void run() {
            mText.setText("counter"+ i);
        }
    });  
}

Upvotes: 1

Snicolas
Snicolas

Reputation: 38168

First, it would be a good idea to change the text before sleeping.

Second, if you do this in a separate thread, you have, nevertheless, to manipulate a widget in the ui thread. Try this :

instead of

mText.setText("counter"+ i); 

try

runOnUIThread( new Runnable() {
    public void run() {
        mText.setText("counter"+ i);
    }
});

Regards, Stéphane

Upvotes: 2

Steven Lemmens
Steven Lemmens

Reputation: 1491

"while (i <= 5)" will make it go on till five. Another solution is to make "i" 1 to start with, instead of 0.

Does this help?

Upvotes: 1

Related Questions