在Android的開發中,非UI線程不能操作UI線程中的控制項,即UI是非安全執行緒的。
我在上一篇文章中這樣說過:
它是非UI安全的,也就是說,不接受非UI線程的修改請求。當我們通過別的線程(非主線程或者說是非原始線程)來修改它的時候,
會拋出這個異常:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
CalledFromWrongThreadException 這個字面上都理解過來了,是說這個請求來自於錯誤的線程。
Only the original thread that created a view hierarchy can touch its views 只有最初建立視圖階層的線程才可以接觸到這些視圖。
有些朋友可以不太明白這樣的解釋,今天我又寫了一個這樣的例子,讓我們來看一下。
為了方便測試,在布局中我只有一個TextView,我通過非UI線程來修改它上面顯示的值。
print?
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(new MyThread()).start();
}
class MyThread implements Runnable {
@Override
public void run() {
TextView txtMsg = (TextView) findViewById(R.id.txtMsg);
txtMsg.setText("Modify");
}
}
可能很多朋友都會正常完成修改TextView上面的值,所以對這個非UI線程來修改UI線程抱有懷疑和不解,因為我們明明是通過一個非UI的線程來修改成功的啊。
這裡涉及到一個多線程的關係。我們知道,一個進程有了兩條或兩條以上的線程我們就可以叫它多線程了,它是多個線程可以同時工作,我來舉個例子,
我到食堂裡吃飯,師傅盡職地在視窗打菜,這就是兩個線程,然後我點了一份TextView,裡面裝著Modify。最後我拿到這份TextView,回到座位上把它給吃了。
這個例子一切正常,所以什麼異常都沒有,然後第二天我又去了這個食堂。這天不知是我去得早了,還是這個師傅動作有些慢了。
我到食堂裡吃飯,師傅一邊XXX一邊在炒菜,我驚呆了。然後他把炒好的TextView端上來,我拋出一個噁心反胃的異常,逃走了再也沒有再來過這家食堂。
這兩個例子,一個報錯了一個沒有,其實就在於我到食堂的時間,師傅是否已經做好了菜,就像上面的例子,UI線程和MyThead線程幾乎是同時執行,
但後者的工作量太少了,更改了TextView上面的字就完成了,這裡UI線程把這個UI展示出來,一切都很正常。但要是我們讓MyThead在run的時候先睡眠幾秒鐘呢?
或者是弄一個按鈕,點擊按鈕後MyThead才開始?這樣都是在UI線程載入完成後才通過非UI線程對它進行修改的,一定會報錯!
這就是多線程編程,有時候你運行若干次,結果正確,並不表明你的邏輯就是對的。我們一定要遵循代碼的規範,保持清晰的思維。
摘自A_Mean的專欄
沒看到那些工作間都寫著嗎,非工作人員禁止入內!!!