Android 进阶解密阅读笔记10
上一篇 Android 进阶解密阅读笔记9 从 WindowManager 开始梳理了相关类还有关联,这篇来梳理下 WindowManagerGlobal 的作用。
WindowManagerGlobal
WindowManagerImpl 对象里包含了一个 WindowManagerGlobal 对象,它是单例实现的,其作用是帮助 WindowManagerImpl 实现一些功能,例如 addView, removeView, updateView。WindowManageGlobal 对象中比较关键的变量有 mViews, mRoots, mParams。
ViewRootImpl
描述了视图树的根节点,用于 View 与 WindowManager 的交互。一个 ViewRootImpl 可以理解为一个视图树。
来看下 WindowManagerGlobal 的 addView 方法的实现,
//WindowManagerGlobal
public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {
ViewRootImpl root;
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
try {
//可以看到最终是通过 ViewRootImpl 将要添加展示的 View 设置进来并和 Display 对象关联的
root.setView(view, wparams, panelParentView);
}
}
//ViewRootImpl
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
int res; /* = WindowManagerImpl.ADD_OKAY; */
try {
mOrigWindowType = mWindowAttributes.type;
//挑关键的看,这里通过 mWindowSession 的 addToDisplay 来完成 View 的添加
//mWindowSession 在创建 ViewRootImpl 时被创建赋值
//mWindowSession = WindowManagerGlobal.getWindowSession();
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,mTempInsets);
}
}
}
//WindowManagerGlobal
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
//右侧调用的方法已经比较明确了,应该就是获取 WMS 的
//而左边这种写法就有点获取 AMS 服务的味道了
IWindowManager windowManager = getWindowManagerService();
//通过 WindowManagerService 创建 Session 对象
//Session 继承自 IWindowSession.Stub,这种感觉依然是跨进程通信
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
});
}
}
}
}
//就像获取 AMS 服务那样,获取 WMS 也是通过 AIDL 来实现的
//IWindowManager 定义了服务内容,最终的获取到的就是 WindowManagerService
//其实这个服务会在系统服务进程启动时作为其他服务模块被启动加载,相对 AMS 等级低一些
public static IWindowManager getWindowManagerService() {
synchronized (WindowManagerGlobal.class) {
if (sWindowManagerService == null) {
sWindowManagerService = IWindowManager
.Stub.asInterface(ServiceManager.getService("window"));
}
return sWindowManagerService;
}
}
综上,一个 View 的添加过程从 WindowManager 开始会经过 WindowManagerGlobal,再到 ViewRootImpl,再进行跨进程通信,通过 Session 转向 WindowManagerService 来实现。
updateView
相比 View 的增,删,更新视图的过程会较复杂些。首先通过 WindowManagerGlobal 的 updateViewLayout 方法对 mRoots,mParams 进行操作更新,然后调用 ViewRootImpl 对象的 setLayoutParams 方法。setLayoutParams 方法里主要是设置一些属性参数,并最终调用 scheduleTraversals ,这个方法就是作为 View 的工作流程的开始,在方法里会通过 Choreographer 类型对象协调进行 View 的刷新。最后会继续调用 ViewRootImpl 的 performTraversals 开始了 View 的测量,布局,绘制工作。