整体流程非常多,本文看其中一部分。
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,都会创建一个ViewRootImpl,并将它保存在WindowManagerGlobal的ArrayList<ViewRootImpl> mRoots
中,而这个根view也会保存在它的变量ArrayList<View> mViews
中; 根view所有的参数保存在ArrayList<WindowManager.LayoutParams> mParams
中。
普通View添加到VG是就是把该View加入到VG的mChildren数组中而已。
#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的实现类,其实是个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用于保存窗口状态,并且win.openInputChannel(outInputChannel);开启事件传输通道。将IWindow和windowstate保存到一个map中,window持有session,wms从而将应用层各个IWindow和seession以及windowstate一一对应起来。这会用于判断事件分发到哪个窗口和具体分发中用到。
。
上面是resume中的过程,调用addView()显示过程,在resume之前,setcontentview并没有显示,只是创建了decorview,windowmanagerservice还不知道有新的window,当handleResumeActivity()中调用addView()之后才会ipc通知windowmanagerservice添加新的window并显示。
windowManagerImpl 为 wWindowManager 的实现类。WindowmanagerImpl 内部方法实现都是由代理类WindowManagerGlobal完成,而WindowManagerGlobal 是一个单例,也就是一个进程中只有一个windowManagerGlobal 对象服务于所有页面的View。
网友评论