前言
在梳理 Android 必备知识过程中,想理解 Activity.setContentView 之后到显示出 View 的过程背后到底干了什么,将阅读和分析完源码之后知识点输出到博客进行记录和备忘
问题
- 如果让你实现 WMS,你怎么做
- 如果让你实现 WMGlobal,你怎么做
- WMS 如何管理 Window
- Window 如何管理 View
- 如果让你修改 WMS 的代码,你能改吗
数据结构
Client / Server 模型
- Server 端 WindowManagerService 对象
- Client 端 Session 对象
- Client 和 Server 之间通过 Binder 进行 IPC 通信
结构图
Server 端
wms.server.pngClient 端
wms.client.pngUML 类图
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 的添加过程
网友评论