我们一般接受的思想就是不要在子线程中更新UI,为什么呢?这你就不得不提到 activity的启动过程中的检查机制.
public void setContentView(View view, ViewGroup.LayoutParams params) {
// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
// decor, when theme attributes and the like are crystalized. Do not check the feature
// before this happens.
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
view.setLayoutParams(params);
final Scene newScene = new Scene(mContentParent, view);
transitionTo(newScene);
} else {
mContentParent.addView(view, params);
}
mContentParent.requestApplyInsets();
final Window.Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
执行完上面的setContentView后,DecorView还没有被WindowManager正式添加到Window中,接着会调用到ActivityThread类的handleResumeActivity方法将顶层视图DecorView添加到PhoneWindow窗口,handleResumeActivity中需要执行addView方法,WindowManagerImpl 将 addView操作交给WindowManagerGlobal来实现,WindowManagerGlobal的addView函数中创建了一个ViewRootImpl对象root,然后调用ViewRootImpl类中的setView成员方法,setView中主要做:
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
我们看到有这个checkThread,他就是来保证我们必须在ui线程中更新view,那么是不是子线程就不能更新ui了呢,,并不是这样的,你在oncreate中执行ui更新时:
(new Thread(){
@Override
public void run() {
super.run();
Log.e("pid",Thread.currentThread().getId()+"");
((TextView)findViewById(R.id.keep)).setText("测试代码");
}
}).start();
checkThread方法没执行到,这时候你相当于可以设置ui,但是你设置线程sleep几秒后,在更新,就会报错,只适合checkTread已经执行到了。