前言
在梳理 Android 必备知识过程中,想理解 Activity.setContentView 之后到显示出 View 的过程背后到底干了什么,将阅读和分析完源码之后知识点输出到博客进行记录和备忘
问题
如果让你实现 WMS,你怎么做
如果让你实现 WMGlobal,你怎么做
WMS 如何管理 Window
Window 如何管理 View
如果让你修改 WMS 的代码,你能改吗
数据结构
Client / Server 模型
Server 端 WindowManagerService 对象
Client 端 Session 对象
Client 和 Server 之间通过 Binder 进行 IPC 通信
结构图
Server 端
wms.server.png
Client 端
wms.client.png
UML 类图
WMS.addWindow.png
蓝色代表 SystemServer 进程空间,白色代表 App 进程空间
WMS 内部记录所有 Session 和 WindowState 对象信息,是整个 Window 信息处理的中心
Session 是 WMS 看到的 App 进程,某一 App 进程内的所有 Window 都属于同一个 Session 对象
WindowState 是 WMS 管理 Window 的单元,本身是树形结构,即 Window 树。它记录自己从属的 Session 和 App 端的 IWindow Binder 对象
WindowManagerGlobal 是 App 进程的 WindowManager 真正干活的类,记录当前进程空间内所有 Window 的 DecorView、ViewRootImpl、LayoutParams 以及 WMS 的 Binder 代理和 Session 信息
WindowManagerImpl 是 WindowManager 接口的实现类,每个 Window 都有独立的 WindowManagerImpl 实例
PhoneWindow 是 Window 的实现类,记录 DecorView
ViewRootImpl 是控件树的祖先节点,负责与 WMS 通信
DecorView 是 Window 的根 View,负责装饰开发者的 View
IWindow 是一个 Binder ,用于 WMS 与 App 进程间 Window 的通信,它的 API 运行在 Binder 线程池中,需要通过 ViewRootImpl 内部的 Handler 切换到主线程执行
Activity 是用户活动,记录 Window 和 WindowManager
基本操作
UML 序列图
Activity.setContentView.png
Activity 对象转发 setContentView 消息给内部 PhoneWindow
PhoneWindow 创建 DecorView,先把输入 View 挂到一个 LinearLayout 下,再把 LinearLayout 挂到 DecorView 下面。到这里 App 空间的控件树已经绑定完毕
ActivityThread 收到 AMS 的 scheduleResumeActivity 消息并从 Binder 线程池中通过
Handler 调度到主线程后给 ActivityThread 发送 handleResumeActivity 消息
Activity 收到 onResume 之后,由 ActivityThread 判断 Activity 的窗口未添加(mWindowAdded 为 false),此时向 WindowManagerImpl 发送 addView 消息
WindowManagerImpl 把消息转发给 WindowManagerGlobal 对象
WindowManagerGlobal 负责创建 ViewRootImpl,并且把 View, ViewRootImpl, LayoutParams 三个信息保存在其内部的数组中
ViewRootImpl 通过 Binder IPC 向 WMS 请求 openSession ,拿到 WMS 创建的 Session Binder 对象的代理
ViewRootImpl 创建 IWindow.Stub Binder 对象,用于传给 WMS 标识一个 Window 对象
ViewRootImpl 收到 setView 信息,开始第一次 requestLayout, 异步刷新布局
ViewRootImpl 向 mWindowSession Binder Proxy 对象发送 addToDisplay 消息,参数是 IWindow Binder 对象
SystemServer 进程 Session Binder 实体对象收到 addToDisplay 消息,告诉 WMS addWindow 消息
WMS 创建 WindowState 对象封装 App 进程传递过来的 IWindow Binder 对象,把 WindowState 记录在内部的 mWindowMap 映射表里面,并向 WindowState 对象发送 attach 消息
WindowState 向 Session 发送 windowAddedLocked 消息
Session 收到消息后把自己记录在 WMS 的 mSessions 数组里面,到这里 WMS 已经记录了 App 的一个 IWindow 对象
接下来就是 ViewRootImpl 收到 performTraverse 进行整个控件树的 measure , layout, draw 信息处理
锁住 Surface 对象,通过 Canvas 对象进行渲染,解锁后发送到显存供显卡读取显示
练习题
单步跟踪 App 进程和 SystemServer 进程的 Window 添加流程
理解 Window, DecorView, ViewRootImpl, Session, IWindow, WindowState 的创建时机
画出 UML 类图,理解数据结构
画出 UML 序列图,理解消息的处理过程
按模块分析 WMS 添加、删除、更新 Window 的过程
总结
在理清相关数据结构的前提下,跟踪信息传递过程,抓关键对象的创建和绑定时机,理解 Window 的添加过程