没有错误“只有创建视图层次结构的原始线程可以触摸其视图”在视图更新时没有延迟

我遇到了一个有趣的问题。 如果在onCreate/onStart/onResume活动方法中编写以下代码:

 final Button myButton = (Button)findViewById(R.id.myButton); final TextView myTextView = (TextView)findViewById(R.id.myTextView); final Thread thread = new Thread(new Runnable() { @Override public void run() { myTextView.setText("Hello text"); } }); myButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { thread.start(); } }); 

要么:

 final TextView myTextView = (TextView)findViewById(R.id.myTextView); final Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.currentThread().sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } myTextView.setText("Hello text"); } }); thread.start(); 

应该如何,抛出一个错误

 android.view.ViewRoot $ CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views." 

很明显,在这种情况下,我必须更新ui-thread中的视图 (Handler, AsyncTask, runOnUiThread, view.post).

但是如果你在没有延迟的情况下更新另一个线程中的视图(没有睡眠调用或没有通过按下按钮启动线程), 则不会抛出exception

 final TextView myTextView = (TextView)findViewById(R.id.myTextView); final Thread thread = new Thread(new Runnable() { @Override public void run() { myTextView.setText("Hello text"); } }); thread.start(); 

谁能告诉我为什么会有这样的行为?

更新:

我已经学习了Android的源代码并得出以下结论。 南德斯写下了真相。 初始化视图时,调用View的dispatchAttachedToWindow(AttachInfo info,int visibility)方法,初始化mAttachInfo字段。 mAttachInfo对象具有mViewRootImpl字段。 如果为null,则getViewRootImpl将返回null:

 public ViewRootImpl getViewRootImpl() { if (mAttachInfo != null) { return mAttachInfo.mViewRootImpl; } return null; } 

ViewRootImpl包含checkThread方法。 它比较线程:创建视图的线程和视图更新请求的线程。

  void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); } } 

因此,如果视图未初始化,则不会检查和更改不会抛出exception。

仅当textView重新布局完成时才会检查线程。 但只有在调用OnCreate之后才能进行视图的Layouting。 因此,直到Ui未显示,更改textView不会导致视图无效。

但是一旦显示了textView,就需要重新布局UI,在这种情况下检查线程。 因此,只有在Oncreate的一段时间后才能获得exception但不会立即获得exception。