上篇文章:子线程更新主线程的View抛出异常全过程,ViewRootImpl的checkThread方法中,通过mThread来判断,要更新View的线程和创建View的线程,是不是同一个,如果不是就抛出异常。
void checkThread() {if (mThread != Thread.currentThread()) {throw new CalledFromWrongThreadException("Only the original thread that created a view hierarchy can touch its views.");}}
那么这个mThread是什么时候被赋值的了?
本文目录
- ViewRootImpl的mThread什么时候赋的值?
- ViewRootImpl对象什么时候生成的?
- 其他疑问
ViewRootImpl的mThread什么时候赋的值?
在ViewRootImpl对象生成的时候,也就是ViewRootImpl的构造函数里面赋的值。
/frameworks/base/core/java/android/view/ViewRootImpl.java
public ViewRootImpl(Context context, Display display) {......mThread = Thread.currentThread();......
}
在子线程中更新view的问题
ViewRootImpl对象什么时候生成的?
//Activity.javavoid makeVisible() {if (!mWindowAdded) {ViewManager wm = getWindowManager();wm.addView(mDecor, getWindow().getAttributes());mWindowAdded = true;}mDecor.setVisibility(View.VISIBLE);}//getWindowManager返回了mWindowManagerpublic WindowManager getWindowManager() {return mWindowManager;}private WindowManager mWindowManager;
ViewManager是一个接口,WindowManager也是一个接口,WindowManager继承自ViewManager。如下:
/frameworks/base/core/java/android/view/ViewManager.java
/frameworks/base/core/java/android/view/WindowManager.java
public interface ViewManager//定义对View的增删改
{public void addView(View view, ViewGroup.LayoutParams params);public void updateViewLayout(View view, ViewGroup.LayoutParams params);public void removeView(View view);
}public interface WindowManager extends ViewManager { //可见WindowManager也提供对View的增删改的接口方法......
}
WindowManager的具体实现类是WindowManagerImpl
,我们看看WindowManagerImpl#addView()方法。
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {applyDefaultToken(params);mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,mContext.getUserId());
}//mGlobal 是WindowManagerGlobal类的对象
public final class WindowManagerImpl implements WindowManager {private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();......
}
接着看WindowManagerGlobal#addView()方法。
/frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow, int userId) {......ViewRootImpl root;View panelParentView = null;synchronized (mLock) {...//创建ViewRootImpl对象root = new ViewRootImpl(view.getContext(), display);//设置View的布局属性view.setLayoutParams(wparams);//将相关信息保存到对应集合mViews.add(view);mRoots.add(root);mParams.add(wparams);try {root.setView(view, wparams, panelParentView, userId);//调用ViewRootImpl对象的setView方法(这里也是View绘制的根源)} catch (RuntimeException e) {...}}
}
在WindowManagerGlobal#addView()方法里,我们看到了ViewRootImpl对象的初始化。
总结:
WindowManagerGlobal
的addView()方法里面,生成了ViewRootImpl对象。
在子线程中更新view的问题
Window和WindowManager和ViewRootImpl
看到这里,继续追问:ViewRootImpl的初始化确定是在主线程吗?这个问题比较复杂,后面的文章,接着分析。
其他疑问
-
WindowManager与ViewRootImpl是什么关系?
WindowManagerGlobal有存储ViewRootImpl的集合,mRoots。
Window和WindowManager和ViewRootImpl -
mRoots是干啥的?
存储所有的ViewRootImpl。 -
Global为什么要保存ViewRootImpl?
后面会需要查询。 -
一个 Activity 有多少个 ViewRootImpl?
ViewRootImpl 是实际管理 Window 中所有 View 的类,每个 Activity 中 ViewRootImpl 数量取决于调用mWindowManager.addView() 的次数。
Framework篇 - 一文搞懂 Activity、View、Window、ViewRootImpl