1.Activity的显示
Activity的显示原理如下图所示
在Activity启动的时候会创建一个PhoneWindow,而这个PhoneWindow会包含一个DecorView,DecorView就是Activity的rootview,其中包含一个bar和contentView,我们自己写的布局会放到contentView当中。对于每个DecorView都有一个对应的ViewRootImpl对象,能够和WMS进行双向通信,负责DecorView的绘制。
接着我们来看下Activity的显示流程图
有以下几个关键步骤需要我们关注一下
1.setContentView
以下为PhoneWindow当中的setContentView,可以看到我们自己定义的layout被夹在到了mContentParent,所以我们的方法名称才叫做setContentView,而不叫setView。
//PhoneWindow.java
public void setContentView(int layoutResID) {
if (mContentParent == null) {
//1.确保decorView被创建
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
//2.将我们自己定义的layout加载到contentview当中
mLayoutInflater.inflate(layoutResID, mContentParent);
}
......
}
2.handleResumeActivity
如下代码为ActivityThread的handleResumeActivity方法,会触发activity的onResume周期函数。此方法中会将decorView添加到windowmanager当中,并创建ViewRootImpl对象,负责管理view的绘制,因此Activity在onResume周期函数之后才能够可见。
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
//1.执行activity的onresume周期函数
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
......
ViewManager wm = a.getWindowManager();
//2.将decorview添加到windowManager当中
wm.addView(decor, l);
r.activity.makeVisible();
......
}
3.setView
如下代码为ViewRootImpl的setView方法,如注释1所示,会先出发重绘制,然后会调用mWindowSession.addToDisplay方法,将window添加到wms,wms将会给应用分配surface,并掌管surface的尺寸和显示顺序。
ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
......
//1.触发重绘
requestLayout();
......
//2.binder调用,wms通信
mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
......
}