知识点:
1.Window、ViewRoot和DecorView的关系
2.DecorView是什么布局
3.DecorView什么时候显示
一、Window、ViewRoot和DecorView的关系
Android系统在启动Activity时,会先创建activity实例。在在activity实例中创建window实例,decorView便是window创建的。而ViewRoot则是链接window和decorView的纽带。
从源码的角度看,系统启动onResume之前,会调用ActivityThread的handleResumeActivity方法,
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
// TODO Push resumeArgs into the activity for consideration
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
if (r == null) {
// We didn't actually resume the activity, so skipping any follow-up actions.
return;
}
final Activity a = r.activity;//Activity实例
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow(); // Winsow实例
View decor = r.window.getDecorView(); // DecorView实例
decor.setVisibility(View.INVISIBLE); // 默认不可见
ViewManager wm = a.getWindowManager(); // WindowManager实例,ViewManager的子类
WindowManager.LayoutParams l = r.window.getAttributes(); // Winsow布局参数
a.mDecor = decor;
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l); // 关联
}
}
}
······
// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
}
在该方法中依次获取Activity实例、Winsow实例及其布局参数l、DecorView实例、WindowManager实例wm,并通过WindowManager的addView方法将DecorView和window关联起来。
具体如何关联的呢?
WindowManagerImpl对addView方法做了具体实现,
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
最终,WindowManagerGlobal完成了关联任务。代码如下:
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
...
}
}
}
viewRoot通过setView方法,将DecorView和Window关联起来,它是纽带。
继续分析就会发现,Window最终只是需要DecorView在Z轴方向的位置信息。
二、DecorView是什么布局
三、DecorView什么时候显示
在完成关联之后,ActivityThread会调用Activity的makeVisible方法,显示DecorView
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}