Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
737 views
in Technique[技术] by (71.8m points)

java - Android TextView.setText() invoked & returned before Thread.sleep() blocks until sleep() returns. Why?

In the Android framework, if a TextView's setText() method is called, and after it returns Thead.sleep() is called, then the screen of the device does not display the given text until after sleep() has returned. Why?

public class SleeperActivity extends Activity {
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);
    }

    public void doDelay(View view) {
        try {
            TextView textView = (TextView) view;
            textView.setText("Sleeping");
            Log.d("Sleeper", "This log entry is invoked before sleeping");
            Thread.sleep(5000L);
            textView.setText("Ready");
        } catch (InterruptedException e) { finish(); }
    }
}

The layout, not shown, has a button whose onClick attribute is set to doDelay().

When the above code is compiled and run, and the button is clicked, the text passed in the first invocation of setText() does not appear on the screen until after the thread has slept for five seconds, even though the log entry appears in the log before those five seconds begin to elapse.

Why does this happen, and what ought I to do about it to make the text passed in the first call to setText() appear on the screen before the thread begins to sleep?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

1)Never sleep that long on the UI thread. In fact, never sleep on it at all. That causes it to block and makes the phone unresponsive

2)setText calls invalidate on the view. That will cause the framework to draw the view again as soon as its able- but that means needs to finish the current things its doing and get back to the main Looper (basically, it needs to return from whatever method in your code it first calls). Until then, the change won't be visible on screen.

Edit: to put it another way, inside the framework we have

do{
    Message msg = nextMessage();
    if(msg.what == ON_CREATE){
       currentActivity.onCreate();
    }
    else if(msg.what == DRAW){
        rootView.onDraw();
        //draw entire screen
    }
    else 
      ...  //Thousands of more events like touches, handlers, etc

It can't get to the draw message until its done with the current message. Its single threaded.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.9k users

...