Activity的Window创建过程
在ActivityThread的performLaunchActivity方法中创建了Activity,并调用了Activity的attach方法
Activity
attach
在attach方法中,创建了Window的对象,并设置了Window的回调。由此可以看出,Activity中持有的mWIndow对象即为PhoneWindow。
创建PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
从这段代码中可以看出WIndow已经创建完成了。下面接着看Activity的视图是怎么显示在Window上的。
由于Activity的界面显示是由setContentView发起的,所以从setContentView着手分析。
setContentView
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
由上面的这段代码可以得出,Activity的setContentView方法调用了PhoneWindow的setContentView方法。
PhoneWindow
setContentView
1 创建DecorView对象
在setContentView方法中,首先通过installDecor方法创建DecorView
mDecor = generateDecor(-1);
简单介绍一下DecorView,DecorView是一个FrameLayout。是Activity中的顶级的View。此布局会包含一个标题栏和一个内容栏。但是根据设置主题的不同,有可能标题栏会没有。但是内容栏是肯定有的。内容栏对应的id为content。所以当在activity中调用方法R.layout.activity_main。其值就是赋给DecorView中id为content的内容栏。
2 加载具体布局文件到DecorView
在generateDecor方法中,通过下面这行代码,将布局资源赋给DecorView
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
在DecorView中的onResourcesLoaded方法可以看出,直接将布局资源赋值给了mContentRoot。
final View root = inflater.inflate(layoutResource, null);
mContentRoot = (ViewGroup) root;
到此为止,Activity的布局文件已经添加到了DecorView中。
经过上述步骤,可以得出,此时虽然Window对象已经创建,DecorView也已经创建,但是DecorView还并没有添加到Window中。
ActivityThread
handleResumeActivity
在handleResumeActivity方法中首先会调用onResume方法,过程如图
然后会调用Activity的makeVisible方法
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
Activity
makeVisible
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
从这段代码中可以看出,首先获取WindowManager对象,然后通过此WindowManager将DecorView添加到Window中。至此Activity中的Window的创建过程已经分析完了。
Dialog的Window创建过程
Dialog的Window创建过程和Activity类似。有如下几个步骤
1 创建window
在Dialog的构造方法中,创建了Window对象,并设置回调
final Window w = new PhoneWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setOnWindowDismissedCallback(this);
w.setOnWindowSwipeDismissedCallback(() -> {
if (mCancelable) {
cancel();
}
});
2 初始化DecorView并将Dialog的视图添加到DecorView中
在show方法中,给DecorView赋值
mDecor = mWindow.getDecorView();
将布局id添加到DecorView中
public void setContentView(@LayoutRes int layoutResID) {
mWindow.setContentView(layoutResID);
}
3 将DecorView添加到WIndow中
mWindowManager.addView(mDecor, l);
mShowing = true;
对比之前的Activity的window创建过程,可以发现过程是类似的。