我遇到了一個有趣的問題。沒有錯誤「只有創建視圖層次結構的原始線程才能觸及其視圖」當視圖更新沒有延遲
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();
}
});
或:如果您在活動onCreate/onStart/onResume
方法寫代碼如下
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線程的觀點(Handler, AsyncTask, runOnUiThread, view.post).
但是,如果你在更新另一個線程視圖無延遲(不睡覺打電話或沒有通過按下一個按鈕啓動線程),異常不會被拋出。
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();
有人可以告訴我爲什麼會有這樣的行爲嗎?
UPDATE:
我已經學會了Android的源代碼,並得出如下結論。南日什寫下了真相。 當初始化視圖的視圖調用dispatchAttachedToWindow(AttachInfo info,int visibility)方法時,初始化mAttachInfo字段。 mAttachInfo對象具有mViewRootImpl字段。如果爲空,則getViewRootImpl將返回爲空:
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.");
}
}
因此,如果視圖沒有被初始化,就沒有檢查和更改不拋出異常。
是的,我也試驗過延遲參數。但我想知道爲什麼。 看來,線程需要一些時間進行初始化,在此期間,我們可能會改變UI組件。但在文檔中我沒有看到這一點。 –
我認爲「延遲」是由於什麼'nandeesh'他回答說。這可能是答案。 – Luksprog