Android 的绘制原理是一个从应用层 View 树计算到系统层 SurfaceFlinger 合成渲染的完整链路,核心围绕 ** 测量(Measure)- 布局(Layout)- 绘制(Draw)** 三大流程展开,并结合 VSync 信号同步、GPU 硬件加速等机制保障流畅性。以下是详细拆解:
一、绘制架构分层
Android 绘制体系从上到下分为四层,各层职责明确:
应用层:Activity、View/ViewGroup(UI 组件),定义 UI 结构和绘制逻辑;Framework 层:ViewRootImpl(连接 View 和系统服务的桥梁)、Canvas(绘制 API)、DisplayList(绘制指令缓存)、Choreographer(VSync 信号处理);系统服务层:SurfaceFlinger(核心合成服务),负责多窗口 Surface 的合成;硬件层:GPU(图形渲染)、Display(屏幕显示)、HAL(硬件抽象层)。
二、绘制触发时机
当需要更新 UI 时,会触发绘制流程,常见场景:
首次加载 Activity(onCreate→onResume 后,ViewRootImpl 初始化触发);调用/
View.invalidate()(主动刷新 UI);窗口变化(如横竖屏切换、软键盘弹出);动画执行、触摸反馈等动态操作。
ViewGroup.requestLayout()
三、核心流程:Measure→Layout→Draw
这三大流程由方法驱动,该方法是绘制的总入口,由 Choreographer 接收 VSync 信号后触发。
ViewRootImpl.performTraversals()
1. 测量(Measure)
目标:计算 View/ViewGroup 的实际宽高(/
mMeasuredWidth)。流程:
mMeasuredHeight
从根 View(DecorView)开始,自上而下遍历 View 树;每个 View 调用,根据父 View 的约束(MeasureSpec:EXACTLY/AT_MOST/UNSPECIFIED)计算自身尺寸;ViewGroup 需遍历子 View,调用
onMeasure(int widthMeasureSpec, int heightMeasureSpec)传递约束,再根据子 View 尺寸确定自身尺寸(如 LinearLayout 的 orientation 决定布局方向)。
child.measure(...)
MeasureSpec:由父 View 的尺寸和自身/
layout_width(match_parent/wrap_content/ 固定值)共同决定,是测量的核心约束。
layout_height
2. 布局(Layout)
目标:确定 View 在父容器中的具体位置(/
mLeft/
mTop/
mRight)。流程:
mBottom
仍从根 View 开始自上而下遍历;每个 ViewGroup 调用,计算子 View 的位置并调用
onLayout(boolean changed, int l, int t, int r, int b);单个 View 的
child.layout(...)方法直接赋值自身位置参数,无额外逻辑。
layout(...)
示例:RelativeLayout 通过等属性计算子 View 位置,FrameLayout 则根据
layout_alignParentRight堆叠子 View。
layout_gravity
3. 绘制(Draw)
目标:将 View 的内容渲染到屏幕上,分为软件绘制和硬件绘制(硬件加速开启时)。流程(以硬件加速为例):
遍历 View 树,每个 View 调用,通过 Canvas API(drawRect/drawText/drawBitmap)生成DisplayList(绘制指令列表);ViewRootImpl 将 DisplayList 提交给 SurfaceFlinger;SurfaceFlinger 将多个窗口的 Surface(如应用窗口、状态栏、导航栏)合成,通过 GPU 渲染到 FrameBuffer,最终由屏幕显示。
onDraw(Canvas canvas)
软件绘制:无 DisplayList 缓存,直接通过 CPU 将像素绘制到 Bitmap,效率较低(API 14 后默认开启硬件加速)。
四、关键机制:VSync 与 Choreographer
为避免屏幕撕裂(GPU 渲染帧率与屏幕刷新率不同步),Android 引入 **VSync(垂直同步)** 机制:
屏幕刷新率固定(如 60Hz,每 16.6ms 发送一次 VSync 信号);Choreographer 接收 VSync 信号后,将绘制任务()加入主线程 MessageQueue,确保每次绘制都对齐屏幕刷新周期;若绘制耗时超过 16.6ms(如 onDraw 中做复杂计算),会导致掉帧(Frame Drop),表现为 UI 卡顿。
performTraversals()
五、Surface 与 SurfaceFlinger
Surface:每个应用窗口对应一个 Surface,是绘制的 “画布”,底层关联一块 GPU 可访问的内存(GraphicBuffer);SurfaceFlinger:Android 系统的核心合成服务,负责管理所有 Surface,将多个 Surface 按 Z 轴顺序合成(如状态栏在最上层),最终输出到屏幕。应用层通过或 ViewRootImpl 与 Surface 交互,SurfaceFlinger 通过 Binder 与应用进程通信。
SurfaceHolder
六、硬件加速原理
硬件加速将绘制操作从 CPU 转移到 GPU,核心是DisplayList 缓存和GPU 并行计算:
首次绘制时生成 DisplayList(绘制指令),后续刷新若 View 未变化,直接复用 DisplayList,无需重新计算;Canvas API 不再直接绘制像素,而是转换为 GPU 可执行的 OpenGL ES 指令,GPU 通过并行计算快速渲染;仅支持部分 Canvas API(如的部分模式在硬件加速下不兼容),需注意兼容性。
PorterDuffXfermode
七、总结
Android 绘制的核心链路: →
UI触发刷新 →
ViewRootImpl.performTraversals() →
Measure→Layout→Draw生成DisplayList →
Choreographer对齐VSync →
SurfaceFlinger合成Surface
GPU渲染→屏幕显示
理解这一流程是优化 UI 性能(如减少过度绘制、避免频繁 requestLayout)的基础。
