子线程中更新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。并发