我们知道一个DecorView的创建是在Activity中调用setContentView后,一步一步实现的。那么,创建好了DecorView后,我们是怎么将它加入进window呢?
调用startActivity方法时,最终会调用ActivityThread的handleLaunchActivity方法创建Activity。在该方法中会调用performLaunchActivity方法,创建一个Activity。
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity a = performLaunchActivity(r, customIntent);
.......
}
在performLaunchActivity方法中,会调用attach方法实例化一个PhoneWindow。
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
mWindow = new PhoneWindow(this);
mWindow.setCallback(this);
attach方法之后会调用callActivityOnCreate方法,进而调用Activity的onCreate方法。
在该方法中首先会调用performResumeActivity方法,进而调用Activity的onResume方法。接着会调用getDecorView方法得到DecorView,然后调用getWindowManager方法得到一个WindowManager(继承了接口ViewManager的接口),最后调用该接口的addView方法将DecorView添加进去。
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
if (!r.activity.mFinished && r.startsNotResumed) {
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
}
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
wm.addView方法调用后,实际上是进入了WindowManageImpl实现类。在该类中实例化一个WindowManagerGlobal,调用addView方法,将DecorView添加进去。
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
........
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
.........
}
public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {
......
ViewRootImpl root;
View panelParentView = null;
......
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
}
在该方法中首先会实例化一个ViewRootImpl,在调用ViewRootImpl的setView方法将DecorView加载到Window中,在setView方法中会调用window的addToDisplay方法,将DecorView显示出来,decorview会将WindowManagerImpl设置为顶层ViewGroup。然后进行绘制过程,将View绘制出来。
在该方法中依次调用performMeasure,performLayout和performDraw方法,其内部分别调用measure,layout,draw方法,完成View的绘制。