2012-10-25 43 views
8

我遇到了一個有趣的問題。沒有錯誤「只有創建視圖層次結構的原始線程才能觸及其視圖」當視圖更新沒有延遲

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."); 
     } 
    } 

因此,如果視圖沒有被初始化,就沒有檢查和更改不拋出異常。

+0

是的,我也試驗過延遲參數。但我想知道爲什麼。 看來,線程需要一些時間進行初始化,在此期間,我們可能會改變UI組件。但在文檔中我沒有看到這一點。 –

+0

我認爲「延遲」是由於什麼'nandeesh'他回答說。這可能是答案。 – Luksprog

回答

9

線程的檢查是目前只有textView重新佈局完成。但視圖的佈局只在調用OnCreate後才能完成。因此,直到沒有顯示Ui,更改textView不會導致視圖無效。

但是一旦TextView的已經顯示,則需要重新佈局UI,在這種情況下,線程被選中。所以你只能在Oncreate的一段時間後才能得到異常,但不是立即。

+0

感謝您的答覆。是非常相似的真相。 –

相關問題