Android的界面組件不能被子線程訪問是什麼意思呢?

然後需要用handler繞過, 那到底什麼算是界面組件? 是View? 還是View所在的Activity, 還是和Activity共享一個線程的其他Service? 那UI線程和子線程通信是不是一定要用Handler?


界面更新發生在ViewRoot執行performTraversals時,會讓每個視圖更新自己的內容。觸發它的方法之一是視圖的invalidate,聲明圖像緩存中某個區域需要更新,此時會先scheludeTraversals,待到下一次vsync信號到來時執行performTraversals。invalidate方法的調用最後會導致checkThread(從ThreadLocal中取出當前線程的Looper,判斷和MainLooper是否為同一個對象),如果不是主線程就拋出錯誤,這是因為Android繪圖線程是單線程模型的設計。


android.view和android.widget下的組件都必需在main thread訪問


因為如果ui可以被子線程訪問修改,必然就會出現各種多線程的問題,比如好幾個線程同時去更新繪製同一個view,導致界面混亂等問題。要想避免這個這個問題,那就加鎖唄,那這樣豈不是提高程序員成本,而且會導致性能下降,更加不流暢,所以google規定了android不可在非ui線程更新ui,如果這樣做了會從framework拋出異常,並提供了Handler機制來讓我們很容易的解決子線程更新UI的問題。


ui線程也就是主線程,反應在應用層基本是四大組件的運行和回調

在這些裡面都能更新ui(主要是activity),包括view,widget,dialog,toast,fragment等

其他new Thread()就是子線程了,無法更新ui,可以使用runOnMainThread或者Handler來運行更新ui的Runnable,或者使用Handler通知到Activity或者View等來更新ui


一開始的那個線程叫做主線程,主線程上面創建UI組件。你後面new出來的都是子線程。

組件是指android.view.View派生出來的所有東西。

訪問組件看似是一個函數,但是它裡面有很多代碼,總之它不是原子的。如果你用幾個線程同時執行這一個函數,就會發生踩踏,即執行的代碼交叉到一塊去了,就會產生各種匪夷所思的效果。


UI組件的更新一定要在UI線程里執行。比如你通過message在另外的線程里執行完你要的操作後,最後通過handler更新UI, 這個更新的操作其實是在UI線程里執行的。


說界面組件不準確,應該說是UI線程 也就是主線程。


推薦閱讀:

操作系統時間調度基本單位是內核線程還是進程?
非同步,多線程和並行的區別?
對於單核cpu而言,開多線程的目的難倒只能是為了防止阻塞么?

TAG:Android開發 | Java編程 | 多線程 |