activity的setContentView()之后,需要在App和WindowManagerService之间建立联系。
首先向WindowManager(继承自ViewManager)添加decorView,因为decorView包含整个activity的GUI。
添加过程是在handleResumeActivity@ActivityThread.java中完成的。
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
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);
}
之后WindowManager的实现类WindowManagerImpl会创建与之对应的ViewRoot来管理该窗口的rootview。这个RootView就是之前设置的contentView。
ViewRoot用来与全局的窗口管理器交互。ViewRoot有一个nested class(静态内部类) W。W是Binder的子类,它用来接受全局窗口管理器的各种消息,例如按键,触摸等。
ViewRoot中有W类型的成员mWindow,ViewRoot在构造方法中创建W的实例并赋值给mWindow。
ViewRoot是Handler的子类,W会通过Looper把消息传递给ViewRoot,ViewRoot.setView()把mWindow传递给上sWindowSession。
前面提到的全局窗口管理器,是一个Service,运行在SystemServer中。ViewRoot通过接口IWindowSession与之交互。其中IWindowSession的实体在WMS中定义。
我们可以看一下ViewRoot.setView()方法,这里面需要关注的两句代码:
requestLayout();
try {
res = sWindowSession.add(mWindow, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets);
} catch (RemoteException e) {...
通过sWindowSession.add(...方法,我们将mWindow参数传递给WMS,这样WMS就可以反向通知ViewRoot的接口。
值得注意的是requestLayout(),这个方法是WMS绘制GUI的。但似乎他是在和WMS建立联系之前绘制的。
前面提到过ViewRoot是一个Handler,它和ActivityThread共用同一个MessageQueue。ActivityThread的handler函数在注册启动一个新的activity的请求处理时,
这个处理过程会调用ViewRoot.setView ()方法。而requestLayout()实际是向MessageQueue发送一个绘制GUI的消息。因此这个消息的处理会在之前的请求处理完成之后才开始。
本文深入解析了Android中Activity的setContentView()方法执行后,如何与WindowManagerService建立联系的过程,包括向WindowManager添加decorView,以及ViewRoot与WindowManager之间的交互,最终实现GUI的绘制。

被折叠的 条评论
为什么被折叠?



