啟動(dòng)一個(gè)Activity
startActivity
最終會(huì)走到ActivityThread的performLaunchActivity
這個(gè)函數(shù)里面會(huì)經(jīng)過層層深入會(huì)調(diào)用 Activity 的 OnCreate() 方法判导,而在 performLaunchActivity() 中調(diào) OnCreate() 方法前會(huì)調(diào)用 Activity 的 attach() 方法
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
//創(chuàng)建PhoneWindow嫉父,并設(shè)置回調(diào)
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(mWindowControllerCallback);
mWindow.setCallback(this);
//將window跟windowmanager綁定
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
//設(shè)置管理window的windowmanager
mWindowManager = mWindow.getWindowManager();
繼續(xù)看Window源碼setWindowManager
/**
* Set the window manager for use by this Window to, for example,
* display panels. This is <em>not</em> used for displaying the
* Window itself -- that must be done by the client.
*
* @param wm The window manager for adding new windows.
*/
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated;
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
這里沒有理解清楚是如何獲取wms
該方法里面可以看到如果傳入的 wm 為空則將其重新賦值。這里其實(shí)是獲取了 WindowManagerService 的代理眼刃,因?yàn)?WindowManagerService 和 Activity 所在的應(yīng)用不在一個(gè)進(jìn)程里绕辖,這里是通過 Binder 通信獲取的一個(gè) WindowManagerService 代理。獲取完 WindowManagerService 代理后通過它來創(chuàng)建出一個(gè)真正要用的 WindowManager 并賦值擂红。即這句代碼:
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mContext, parentWindow);
}
這里主要就是獲取一個(gè)WindowManagerImpl
attatch主要?jiǎng)?chuàng)建出activity的window綁定windowmanager仪际,從而獲取管理當(dāng)前window的windowmanager,但是并沒有將activity的view添加到window
- 繼續(xù)看setContentView
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
查看PhoneWindow源碼setContentView
public void setContentView(int layoutResID) {
// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
// decor, when theme attributes and the like are crystalized. Do not check the feature
// before this happens.
if (mContentParent == null) {
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 {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
主要關(guān)注installDecor()
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this);
}
}
通過源碼得知篮条,如果當(dāng)前DecorView為空弟头,那么就創(chuàng)建一個(gè),并且跟window進(jìn)行綁定涉茧,DecorView 是 Activity 中的頂級(jí) View赴恨,是一個(gè) FrameLayout。
不過現(xiàn)在仍然沒有將對(duì)應(yīng)的畫面展示到手機(jī)屏幕上
Window 加入到 WindowManager 這一過程要在調(diào)用完 Acitivy 的 onResume() 方法后來實(shí)現(xiàn)伴栓,之后會(huì)調(diào)用 Activity 的 makeVisible():
/**
* Control whether this activity's main window is visible. This is intended
* only for the special case of an activity that is not going to show a
* UI itself, but can't just finish prior to onResume() because it needs
* to wait for a service binding or such. Setting this to false allows
* you to prevent your UI from being shown during that time.
*
* <p>The default value for this is taken from the
* {@link android.R.attr#windowNoDisplay} attribute of the activity's theme.
*/
public void setVisible(boolean visible) {
if (mVisibleFromClient != visible) {
mVisibleFromClient = visible;
if (mVisibleFromServer) {
if (visible) makeVisible();
else mDecor.setVisibility(View.INVISIBLE);
}
}
}
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
這個(gè)函數(shù)里首先判斷 Window 是否已經(jīng)添加到 WindowManager 中伦连,沒有的話取出在剛剛 attach() 方法中創(chuàng)建的 WindowManager雨饺,將 DecorView 加入進(jìn)去,這里的 DecorView 其實(shí)就是 Window 所持有那個(gè)惑淳。然后再將 DecorView 設(shè)置為顯示狀態(tài)额港,來顯示我們的布局。
- 至此歧焦,我們需要關(guān)心WindowManager是如何進(jìn)行管理Window
在實(shí)際使用中無法直接訪問 Window移斩,對(duì) Window 的訪問必須通過 WindowManager。我們已經(jīng)知道 WindowManager 提供的三個(gè)接口方法 addView绢馍、updateViewLayout 以及 removeView 都是針對(duì) View 的向瓷,而這些 View 都被其對(duì)應(yīng)的 Window 所持有,所以上面這些操作實(shí)際上相當(dāng)于對(duì) Window 的操作舰涌,WindowManager 是一個(gè)接口猖任,它的真正實(shí)現(xiàn)由上文可知是 WindowManagerImpl 類。
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
}
可以知道瓷耙,實(shí)際是交給了mGlobal進(jìn)行處理朱躺,也就是WindowManagerGlobal
- 繼續(xù)看WindowManagerGlobal源碼的幾個(gè)核心參數(shù)
//存儲(chǔ)的是所有 Window 所對(duì)應(yīng)的 View
private final ArrayList<View> mViews = new ArrayList<View>();
//mRoots 存儲(chǔ)的是所有 Window 所對(duì)應(yīng)的 ViewRootImpl
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
//mParams 存儲(chǔ)的是所有 Window 所對(duì)應(yīng)的布局參數(shù)
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
//mDyingViews 存儲(chǔ)了那些正在被刪除的 View 對(duì)象,或者說是那些已經(jīng)調(diào)用了 removeView 方法但是操作刪除還未完成的 Window 對(duì)象
private final ArraySet<View> mDyingViews = new ArraySet<View>();
在 addView () 方法中將這些相關(guān)對(duì)象添加到對(duì)應(yīng)集合中搁痛。最后調(diào)用 root.setView() 方法长搀,setView() 中會(huì)調(diào)用一個(gè)很重要的方法 requestLayout(),其主要是用來刷新頁面落追,其中還有一個(gè)很重要的方法 addToDisplay
framework/base/services/core/java/com/android/server/wm/Session.java
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
Rect outStableInsets, Rect outOutsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel,
outInsetsState);
}
mWindowSession 的類型是 IWindowSession盈滴,它是一個(gè) Binder 對(duì)象,真正的實(shí)現(xiàn)類是 Session轿钠,這也就是之前提到的 IPC 調(diào)用的位置巢钓。也就是說在這里,完成了 WindowManager 和 WindowManagerService 的通信疗垛,將 Window 信息傳給了WindowManagerService症汹。
至此,得出結(jié)論setView() 方法里面會(huì)通過 mWindowSession 這個(gè) Binder 對(duì)象將 Window 傳給 WindowManagerService贷腕。WindowManagerService 來管理各個(gè) Window 的大小和顯示位置背镇,來讓 SurfaceFlinger 渲染。