外观
WMS 到底管什么?它会帮 View 绘制吗?
标准回答
WMS 是 WindowManagerService。它负责系统侧的窗口管理,包括窗口添加和移除、位置尺寸、层级、可见性、焦点,以及与屏幕配置和转场相关的协调。它要解决的是“有哪些窗口、窗口在哪里、处于什么状态”。
应用侧的 WindowManager 是使用窗口能力的入口;Activity 的 Window 通常由 PhoneWindow 实现,DecorView 是窗口里的顶层 View 容器。ViewRootImpl 协调这棵 View 树与窗口系统的交互,并组织布局、绘制和输入。它们不是 WMS 的不同名字,而是客户端与服务端不同角色。
例如打开一个带按钮的页面:应用创建 View 树并申请接入窗口,WMS 根据窗口类型、token、布局参数和系统策略处理窗口;应用对按钮测量、布局、绘制,渲染出窗口内容;SurfaceFlinger 再结合图层状态处理合成和显示。WMS 不会替 TextView 排版文字,也不会逐个执行按钮的 onDraw。
页面看不见时,要分清窗口有没有创建、是否处于目标屏幕、可见性与层级是否正确,以及内容是否真正绘制提交。窗口存在只是一个条件,不能据此认定用户已经看到了画面。
关键机制
- 客户端 Window / ViewRootImpl 管应用界面接入;服务端 WMS 管全局窗口状态。
- WindowState 是系统侧窗口记录,不是应用的 View 对象。
- 窗口策略、内容绘制、图层合成是协作关系,分别查证据。
通俗例子
按钮 onDraw 已执行但页面仍黑屏:继续看目标窗口是否可见、是否被其他窗口覆盖、图层是否拿到新缓冲区以及何时呈现,而不是反复证明 onDraw 被调用过。
追问与回答
Window token 是什么,为什么会有 BadTokenException?
token 是窗口系统用来关联和校验窗口归属等信息的标识,不是网络登录令牌。某些窗口需要有效的宿主 token;例如页面已经结束却继续弹出依附它的 Dialog,就可能失败。我会核对窗口类型、Context、宿主生命周期和 token,不能靠随便换一个 Context 保证所有弹窗都能显示。
WMS 和 SurfaceFlinger 谁负责动画?
不能简单按“动画都归某一个服务”划分。应用属性动画可能更新 View 并产生新内容;系统转场可以由窗口管理相关组件协调,通过 SurfaceControl 事务改变图层位置、透明度等属性;SurfaceFlinger 按收到的图层状态完成合成。要看动画改变的是 View 内容还是系统图层属性,以及具体版本的实现。
易混淆点
Window、View、Surface 和图层不是固定一一对应。一个普通按钮通常共享所在窗口的内容;SurfaceView 等可能有独立的内容生产与图层路径。
参考资料
内容来源
- Android 技术札记 · 原条目
wms-basics