外观
一个 View 从创建到显示,完整流程是什么?
标准回答
一个普通 View 显示到屏幕,大致经历:创建 View 树并接入窗口,由 ViewRootImpl 安排遍历,在帧调度中完成必要的 measure、layout 和 draw,随后渲染出图像缓冲区,由显示系统合成并展示。
以 Activity 里的一个按钮为例:setContentView 通常先把 XML 创建成 View 对象并放入窗口的内容区域。它解决的是“页面里有哪些控件”,此时不代表控件已经测量,更不代表用户已经看到。窗口接入显示体系后,ViewRootImpl 会协调窗口尺寸、输入和 View 树更新,通过 Choreographer 安排合适的帧工作。
遍历时,measure 计算每个控件需要多大,layout 确定它在父容器里的位置,draw 描述背景、文字和其他内容如何绘制。在常见的硬件加速路径中,主线程主要更新 RenderNode 中的绘制命令与属性,RenderThread 再通过图形后端组织 GPU 渲染,生成窗口的图像缓冲区。
随后,缓冲区和相关同步信息进入显示链路。SurfaceFlinger 将应用窗口与状态栏等图层一起处理,结合 Hardware Composer 的能力完成合成和提交,最后由显示硬件呈现。普通按钮通常画在所属窗口的内容里,并不是每个按钮都有自己的独立 Surface。
所以要分清“View 对象创建好了”“布局完成了”“绘制命令提交了”和“像素已经上屏”。它们是不同阶段。后续仅改变按钮颜色,通常不需要重做整套创建和布局;框架根据更新类型复用已有结果。
关键机制
- 创建与接入:LayoutInflater / setContentView 组织 View 树,Window 承载页面,ViewRootImpl 协调它与窗口系统的交互。
- 应用侧:Choreographer 安排帧回调,ViewRootImpl 执行需要的测量、布局和绘制;硬件加速下再由 RenderThread 与 GPU 处理渲染。
- 显示侧:Surface 对应内容生产入口,缓冲区经队列及事务等机制交接;SurfaceFlinger 与 HWC 处理图层合成和展示。具体队列与同步路径随系统版本演进。
通俗例子
按钮从灰色变成蓝色:主线程修改状态,框架标记需要更新,下一次合适的帧更新绘制内容,GPU 生成新的窗口图像,显示系统展示新帧。setSelected 返回时,只能说明状态调用结束,不能说明蓝色已经出现在屏幕上。
追问与回答
一句话怎样概括?
ViewRootImpl 按帧协调 View 树的测量、布局与绘制,应用渲染出图像缓冲区,SurfaceFlinger 再结合硬件合成能力把多个图层送到屏幕。前三步解释内容怎么画出来,后半段解释画出的内容怎么被用户看见。
为什么只说 measure、layout、draw 还不完整?
因为它们主要描述 View 树在应用侧如何确定尺寸、位置和绘制内容。硬件加速下还有 RenderThread 和 GPU 的工作,随后还要经历缓冲区交接、图层合成和显示。排查“画完了为什么还没显示”时,必须继续看这些后续阶段。
易混淆点
不是每帧都重新 measure / layout,不是所有 View 都有独立 Surface,也不是 onDraw 返回就已上屏。这里描述普通 View 的典型硬件加速路径,SurfaceView 等内容生产方式另看专篇。
参考资料
内容来源
- Android 技术札记 · 原条目
view