在Thread.sleep()阻塞之前调用并返回Android TextView.setText(),直到sleep()返回。 为什么?
在Android框架中,如果调用了TextView
的setText()
方法,并且在它返回后调用了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()
接受一个Runnable
其run()
方法将在事件循环的当前循环完成后调用,并且框架在线程阻塞期间显示了您想要查看的文本。 通过在Runnable
的run()
方法中调用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 ,他的指导让我不知所措地回答了我自己的问题。