子線程中更新UI會報錯的那個方法:java
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:8358)
void checkThread() {
if(mThread!= Thread.currentThread()) {
throw newCalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views.");
}
}
當訪問UI時,ViewRootImpl會調用checkThread方法去檢查當前訪問UI的線程是哪一個,若是不是UI線程則會拋出異常,這是沒問題的。可是爲何一開始在MainActivity的onCreate方法中建立一個子線程訪問UI,程序仍是正常能跑起來呢?android
ViewRootImpl的建立在onResume方法回調以後,而咱們一開篇是在onCreate方法中建立了子線程並訪問UI,在那個時刻,ViewRootImpl是沒有建立的,沒法檢測當前線程是不是UI線程,因此程序沒有崩潰同樣能跑起來,而以後修改了程序,讓線程休眠了200毫秒後,程序就崩了。很明顯200毫秒後ViewRootImpl已經建立了,能夠執行checkThread方法檢查當前線程。安全
那爲何Google要規定不能在子線程中不能更新UI呢:多線程
首先UI線程(mainThread)並非線程安全的,這樣若是子線程修改UI容易數據錯亂,若是作到線程安全的話,這樣作是很低效的。其次谷歌推薦若是子線程須要修改UI可使用handler,這樣的隊列設也是考慮到併發,效率的體現。爲何 android 會設計成只有建立 ViewRootImpl 的原始線程才能更改 UI 呢?這就要說到 Android 的單線程模型了,由於若是支持多線程修改 View 的話,由此產生的線程同步和線程安全問題將是很是繁瑣的,因此 Android 直接就定死了,View 的操做必須在建立它的 UI 線程,從而簡化了系統設計。有沒有能夠在其餘非原始線程更新 UI 的狀況呢?有,SurfaceView 就能夠在其餘線程更新UI。併發