面试复习题–Android的绘制原理

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()
/
ViewGroup.requestLayout()
(主动刷新 UI);窗口变化(如横竖屏切换、软键盘弹出);动画执行、触摸反馈等动态操作。

三、核心流程:Measure→Layout→Draw

这三大流程由
ViewRootImpl.performTraversals()
方法驱动,该方法是绘制的总入口,由 Choreographer 接收 VSync 信号后触发。

1. 测量(Measure)

目标:计算 View/ViewGroup 的实际宽高(
mMeasuredWidth
/
mMeasuredHeight
)。流程

从根 View(DecorView)开始,自上而下遍历 View 树;每个 View 调用
onMeasure(int widthMeasureSpec, int heightMeasureSpec)
,根据父 View 的约束(MeasureSpec:EXACTLY/AT_MOST/UNSPECIFIED)计算自身尺寸;ViewGroup 需遍历子 View,调用
child.measure(...)
传递约束,再根据子 View 尺寸确定自身尺寸(如 LinearLayout 的 orientation 决定布局方向)。

MeasureSpec:由父 View 的尺寸和自身
layout_width
/
layout_height
(match_parent/wrap_content/ 固定值)共同决定,是测量的核心约束。

2. 布局(Layout)

目标:确定 View 在父容器中的具体位置(
mLeft
/
mTop
/
mRight
/
mBottom
)。流程

仍从根 View 开始自上而下遍历;每个 ViewGroup 调用
onLayout(boolean changed, int l, int t, int r, int b)
,计算子 View 的位置并调用
child.layout(...)
;单个 View 的
layout(...)
方法直接赋值自身位置参数,无额外逻辑。

示例:RelativeLayout 通过
layout_alignParentRight
等属性计算子 View 位置,FrameLayout 则根据
layout_gravity
堆叠子 View。

3. 绘制(Draw)

目标:将 View 的内容渲染到屏幕上,分为软件绘制硬件绘制(硬件加速开启时)。流程(以硬件加速为例):

遍历 View 树,每个 View 调用
onDraw(Canvas canvas)
,通过 Canvas API(drawRect/drawText/drawBitmap)生成DisplayList(绘制指令列表);ViewRootImpl 将 DisplayList 提交给 SurfaceFlinger;SurfaceFlinger 将多个窗口的 Surface(如应用窗口、状态栏、导航栏)合成,通过 GPU 渲染到 FrameBuffer,最终由屏幕显示。

软件绘制:无 DisplayList 缓存,直接通过 CPU 将像素绘制到 Bitmap,效率较低(API 14 后默认开启硬件加速)。

四、关键机制:VSync 与 Choreographer

为避免屏幕撕裂(GPU 渲染帧率与屏幕刷新率不同步),Android 引入 **VSync(垂直同步)** 机制:

屏幕刷新率固定(如 60Hz,每 16.6ms 发送一次 VSync 信号);Choreographer 接收 VSync 信号后,将绘制任务(
performTraversals()
)加入主线程 MessageQueue,确保每次绘制都对齐屏幕刷新周期;若绘制耗时超过 16.6ms(如 onDraw 中做复杂计算),会导致掉帧(Frame Drop),表现为 UI 卡顿。

五、Surface 与 SurfaceFlinger

Surface:每个应用窗口对应一个 Surface,是绘制的 “画布”,底层关联一块 GPU 可访问的内存(GraphicBuffer);SurfaceFlinger:Android 系统的核心合成服务,负责管理所有 Surface,将多个 Surface 按 Z 轴顺序合成(如状态栏在最上层),最终输出到屏幕。应用层通过
SurfaceHolder
或 ViewRootImpl 与 Surface 交互,SurfaceFlinger 通过 Binder 与应用进程通信。

六、硬件加速原理

硬件加速将绘制操作从 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)的基础。

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...