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);
......
}