DecorView添加到Window的流程
在Activity的组成结构一文中,了解了Activity的组成,内部持有Window实例,再由这个Window管理布局。Activity中的Window何时被创建并被添加到Activity中的呢?DecorView是如何被加载到Window中的。
1、Window的创建
在Activity启动流程全新版本一文中,详细捋清了Activity的启动流程。顺着继续往下看,让我们跟随Activity的启动流程找到答案。
在ActivityThread中的handleLaunchActivity(...)方法中,处理系统服务的创建Activity回调:
/**
* Extended implementation of activity launch. Used when server requests a launch or relaunch.
*/
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
final Activity a = performLaunchActivity(r, customIntent);
...
}
内部调用另一个方法performLaunchActivity(...)执行真正的Activity创建和初始化相关操作:
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
try {
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);
...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
...
return activity;
}
上面的方法中有重要的两步操作:attach(...)和Activity生命周期的onCreate()回调。
final void attach(Context context,...) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
//Activity内部持有的Window实现类是PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(mWindowControllerCallback);
mWindow.setCallback(this);
...
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
mUiThread = Thread.currentThread();
mMainThread = aThread;
...
mWindowManager = mWindow.getWindowManager();
}
①初始化Activity内部持有的Window,实现现类是PhoneWindow,继承自Window。
②通过Window的setWindowManager(...)方法给Window设置窗口管理器。
③再通过Window获取到WindowManager赋值给Activity中的全局变量mWindowManager。
这里完成了Activity中Window、WindowManager相关的初始化工作。关于Window详见理解Window一文,关于WindowManager详见理解WindowManager一文。
2、DecorView的创建
Activity创建完毕,内部持有的Window也初始化了。继续跟随着Activity的启动流程,完成剩下DecorView添加到Window中的过程。
在Activity启动流程全新版本一文第4.6节知道Activity的onResume()生命周期是通过系统服务发起ResumeActivityItem回调,最终执行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.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;
...
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
}
...
}
handleResumeActivity(...)处理onResume()生命周期回调,内部通过Window的getDecorView()方法获取DecorView实例。getDecorView()方法在抽象类Window还未被实现,前面提到过Activity中的Window实现是PhoneWindow,getDecorView()方法实现如下:
@Override
public final @NonNull View getDecorView() {
if (mDecor == null || mForceDecorInstall) {
installDecor();
}
return mDecor;
}
通过PhoneWindow的installDecor()方法安装DecorView到Window中:
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
...
} else {
mDecor.setWindow(this);
}
//对mDecor进行各种属性、Style设置
...
}
如果PhoneWindow中的mDecor还未被创建,那么就调用generateDecor(int featureId)方法生成一个DecorView。
protected DecorView generateDecor(int featureId) {
// System process doesn't have application context and in that case we need to directly use
// the context we have. Otherwise we want the application context, so we don't cling to the
// activity.
Context context;
...
return new DecorView(context, featureId, this, getAttributes());
}
3、DecorView添加到Window
通过Window拿到DecorView后回到ActivityThread的handleResumeActivity(...)方法中继续
@Override
public void handleResumeActivity(IBinder token,boolean finalStateRequest,boolean isForward,String reason) {
...
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
//通过Activity获取WindowManager,在第一节我们知道在attach()中初始化
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
...
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
//把decor添加到WindowManager中
wm.addView(decor, l);
}
}
...
}
通过Activity获取WindowManager实例wm,在第一节我们知道Activity中的WindowManager在attach(...)中初始化。WindowManager继承自ViewManager。都是关于Window的接口。通过WindowManager将DecorView添加到Window中:
//把decor添加到WindowManager中
wm.addView(decor, l);
WindowManager接口的实现类是WindowManagerImpl,addView()方法实现:
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
}
其实WindowManagerImpl中的大部分操作都是通过内部的WindowManagerGlobal完成
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
...
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, userId);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
在这里创建ViewRootImpl--它不是View,实现了ViewParent接口,作为View和WindowManager之间的桥梁。通过setView(...)将从ActivityThread层层传递过来的DecorView添加到当前Activity的Window中。
到这里DecorView被添加到Window中管理,接下来就开始了View的绘制流程:measure、layout、draw。详见View的绘制流程。