整體流程非常多,本文看其中一部分。
Window從邏輯理解來看,猶如是View的一個容器,Activity上所有顯示的View都會包括在這一個Window之中。但是它并不是一個真正的View,從功能上來講,Window更像是View的幫助類和整體管理類,不管是setContentView或者findview還有getxxtitle、settheme等等,都是通過Window來做的。
//ActivityThread#handleResumeActivity
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
//...
ActivityClientRecord r = performResumeActivity(token, clearHide); // 這里會調用到onResume()方法
if (r != null) {
final Activity a = r.activity;
//...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow(); // 獲得window對象
View decor = r.window.getDecorView(); // 獲得DecorView對象
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager(); // 獲得windowManager對象
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l); // 調用addView方法
}
//...
}
}
}
WindowManager的addView()
是針對根View(即 DecorView)的添加接口,子view的addview()
不會掉用到它,每一個addview都是根view,都會創(chuàng)建一個ViewRootImpl,并將它保存在WindowManagerGlobal的ArrayList<ViewRootImpl> mRoots
中,而這個根view也會保存在它的變量ArrayList<View> mViews
中; 根view所有的參數(shù)保存在ArrayList<WindowManager.LayoutParams> mParams
中。
普通View添加到VG是就是把該View加入到VG的mChildren數(shù)組中而已。
#ViewGroup.java
private void addInArray(View child, int index) {
View[] children = mChildren;
final int count = mChildrenCount;
final int size = children.length;
if (index == count) {
if (size == count) {
mChildren = new View[size + ARRAY_CAPACITY_INCREMENT];
System.arraycopy(children, 0, mChildren, 0, size);
children = mChildren;
}
children[mChildrenCount++] = child;
} else if (index < count) {
if (size == count) {
mChildren = new View[size + ARRAY_CAPACITY_INCREMENT];
System.arraycopy(children, 0, mChildren, 0, index);
System.arraycopy(children, index, mChildren, index + 1, count - index);
children = mChildren;
} else {
System.arraycopy(children, index, children, index + 1, count - index);
}
children[index] = child;
mChildrenCount++;
if (mLastTouchDownIndex >= index) {
mLastTouchDownIndex++;
}
} else {
throw new IndexOutOfBoundsException("index=" + index + " count=" + count);
}
}
//之后設置child.mParent = this;
WindowManager的addView()則是針對DecorView
#WindowManagerGlobal.java
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
...
root.setView(view, wparams, panelParentView, userId);
#ViewRootImpl.java #setView(...)
...
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibleTypes(), inputChannel, mTempInsets,
mTempControls, attachedFrame, compatScale);
//其中還包括inputChannel!!!
...
上面的mWindow并不是剛開始那個Window,而是在ViewRootImpl中新建的一個IWindow的實現(xiàn)類,其實是個Binder對象,
#ViewRootImpl.java
mWindow = new W(this);
static class W extends IWindow.Stub {
private final WeakReference<ViewRootImpl> mViewAncestor;
private final IWindowSession mWindowSession;
W(ViewRootImpl viewAncestor) {
mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
mWindowSession = viewAncestor.mWindowSession;
}
...
}
也就是說把當前Binder傳到了WindowManagerService中去,WindowManagerService通過這個W和應用進程通信,類似于ActivityManagerService和ApplicationThread的通信。W中也維護了一個主線程Handler
WindowManagerService會生成windowstate用于保存窗口狀態(tài),并且win.openInputChannel(outInputChannel);開啟事件傳輸通道。將IWindow和windowstate保存到一個map中,window持有session,wms從而將應用層各個IWindow和seession以及windowstate一一對應起來。這會用于判斷事件分發(fā)到哪個窗口和具體分發(fā)中用到。
。
上面是resume中的過程,調用addView()顯示過程,在resume之前,setcontentview并沒有顯示,只是創(chuàng)建了decorview,windowmanagerservice還不知道有新的window,當handleResumeActivity()中調用addView()之后才會ipc通知windowmanagerservice添加新的window并顯示。
windowManagerImpl 為 wWindowManager 的實現(xiàn)類。WindowmanagerImpl 內部方法實現(xiàn)都是由代理類WindowManagerGlobal完成,而WindowManagerGlobal 是一個單例,也就是一個進程中只有一個windowManagerGlobal 對象服務于所有頁面的View。