在Thread.sleep()阻塞之前调用并返回Android TextView.setText(),直到sleep()返回。 为什么?

在Android框架中,如果调用了TextViewsetText()方法,并且在它返回后调用了Thead.sleep() ,那么在sleep()返回之后,设备的屏幕才会显示给定的文本。 为什么?

 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(); } } } 

未显示的布局有一个按钮,其onClick属性设置为doDelay()

编译并运行上面的代码并单击该按钮时,第一次调用setText()传递的文本不会出现在屏幕上,直到线程睡眠五秒钟,即使日志条目出现在在这五秒钟开始之前记录。

为什么会发生这种情况,我应该怎样做才能使第一次调用setText()传递的文本在线程开始进入睡眠状态之前出现在屏幕上?

1)永远不要在UI线程上睡多久。 事实上,永远不要睡觉。 这导致它阻止并使手机无响应

2)setText调用视图无效。 这将导致框架一旦它能够再次绘制视图 – 但这意味着需要完成它所做的当前事情并返回到主Looper(基本上,它需要从它首先调用的代码中的任何方法返回)。 在此之前,更改将不会在屏幕上显示。

编辑:换句话说,在我们拥有的框架内

 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 

在完成当前消息之前,它无法访问绘制消息。 它的单线程。

观察到的行为的原因是View仅在每个循环完成后通过事件循环重绘。 android onCreate()方法以及触摸事件(如单击按钮)由框架在事件循环中调用。 因此,诸如onCreate()onClick()将在重绘任何View之前执行完成,并且在返回这些方法之后才会在显示上产生可见效果。 只有在框架调用所述方法( onCreate()onClick() )的事件循环周期完成后,才能在这些方法中对View进行更改。

要实现问题中请求的行为,必须完成事件循环周期调用sleep()方法,在该循环中,您调用setText()其中包含要在线程阻塞期间显示的文本。 一种方法是简单地通过调用View.post()来替换对sleep()的调用。 View.post()接受一个Runnablerun()方法将在事件循环的当前循环完成调用并且框架在线程阻塞期间显示了您想要查看的文本。 通过在Runnablerun()方法中调用Thread.sleep()来更改问题中的doDelay()方法,如下所示:

  public void doDelay(View view) { final TextView textView = (TextView) view; textView.setText("Sleeping"); textView.post(new Runnable() { public void run() { try { Log.d("Sleeper", "Thread " + Thread.currentThread() + " going to sleep..."); Thread.sleep(5000L); Log.d("Sleeper", "Thread " + Thread.currentThread() + " now awake"); textView.setText("Ready"); } catch (InterruptedException e) { finish(); } } }); } 

我要感谢Gabe Sechan ,他的指导让我不知所措地回答了我自己的问题。