1. 整体渲染流水线概述
安卓渲染不是单个线程或组件完成,而是多层协作的管道(Pipeline):App 端产生画面 → 系统合成 → 硬件显示。
核心参与者:
- App 侧:UI Thread(主线程)、RenderThread(渲染线程)、Choreographer、Skia(或 Vulkan)
- 系统侧:SurfaceFlinger(合成器)、Hardware Composer (HWC)、BufferQueue
- 硬件侧:GPU、Display Controller
graph TD
A[App: UI Thread] --> B[Record Draw Commands / DisplayList]
B --> C[RenderThread → GPU]
C --> D[Surface / Buffer]
D --> E[SurfaceFlinger]
E --> F[Hardware Composer HWC]
F --> G[Display]
图 1:简化渲染流水线(想象一个从左到右流动的管道动画,水滴代表 Buffer,从 App 流向屏幕)。
官方图形数据流图(来自 Android 源码文档):

动画说明(想象这个图动起来):
- 左侧多个 Renderer(Status Bar、App 等)并行产生 Buffer。
- Buffer 通过 Queue 进入 SurfaceFlinger(中间红色块)。
- SurfaceFlinger + HWC 合成后输出到 Display Controller。
- 整个过程受 VSync(垂直同步)信号严格控制,像心脏跳动一样定时“泵血”。
2. App 端:View 绘制流程(Measure → Layout → Draw)
这是开发者最常接触的部分。
2.1 触发机制:invalidate() vs requestLayout()
invalidate():告诉系统“我外观变了,需要重绘”。只触发 Draw 阶段(不一定重测尺寸)。requestLayout():告诉系统“我的尺寸/位置可能变了”。会触发整个 Measure + Layout + Draw。
开发者建议:
- 改颜色、文本 →
invalidate() - 改大小、添加/移除 View →
requestLayout()
2.2 三大阶段(Traversal)
- Measure(测量):自顶向下,父 View 给子 View 约束(MeasureSpec: EXACTLY / AT_MOST / UNSPECIFIED),子 View 计算期望尺寸。
- Layout(布局):自顶向下,父 View 决定子 View 的具体位置(left/top/right/bottom)。
- Draw(绘制):自顶向下,父 View 先画背景,子 View 再画内容。
官方绘制流程:
动画演示(想象树形结构动画):
- 一棵 View 树从根节点(DecorView)开始闪烁。
- Measure 阶段:从上到下箭头流动,每个节点计算宽高。
- Layout 阶段:从上到下,节点“定位”自己和孩子。
- Draw 阶段:从上到下,每个节点执行
onDraw(Canvas),叶子节点最后画。
代码示例(自定义 View 关键方法):
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// 计算自己的尺寸,考虑 padding 和 children
val width = MeasureSpec.getSize(widthMeasureSpec)
setMeasuredDimension(width, desiredHeight)
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
// 放置子 View
child.layout(...)
}
override fun onDraw(canvas: Canvas) {
// 画背景、内容(开发者重点)
super.onDraw(canvas)
canvas.drawRect(...)
}
性能坑:
- Measure/Layout 太重会导致掉帧(尤其是嵌套太深)。
onDraw中避免对象分配(不要 new Paint/Rect 等)。
3. 硬件加速与 RenderThread
Android 3.0+ 默认开启硬件加速。
- UI Thread:执行 Measure/Layout,记录绘制命令(DisplayList / RenderNode)。
- RenderThread(独立线程):回放命令 → Skia → GPU(OpenGL / Vulkan)。
这让主线程更轻量,动画更流畅。
Skia:2D 图形库,支持硬件后端(OpenGL Skia / Vulkan Skia)。开发者可在开发者选项切换 GPU Renderer 测试性能。
动画说明:
- UI Thread 快速“录制”一堆命令(像拍视频)。
- RenderThread 在后台“播放”到 GPU(并行,不阻塞主线程)。
- 如果命令复杂,RenderThread 也会卡 → 掉帧(Profile GPU Rendering 工具可见)。
4. Choreographer + VSync:60/90/120 FPS 的节奏大师
Choreographer 是“指挥家”,接收 VSync 信号(屏幕刷新信号)。
典型一帧流程(Android 11+):
- VSync 到来 → Choreographer 回调。
- Input 处理 → Animation → Measure/Layout/Draw(UI Thread)。
- RenderThread 渲染 → 提交 Buffer 到 SurfaceFlinger。
- SurfaceFlinger 合成 → HWC 显示。
动画演示(时间线):
- 一条水平时间轴,每 16.6ms(60FPS)一个 VSync 脉冲。
- 脉冲触发 UI Thread 工作(绿色块),RenderThread 工作(蓝色块)。
- 如果某块超过脉冲间隔 → Jank(卡顿),显示上一帧(Triple Buffering 缓解)。
开发者工具:
adb shell dumpsys gfxinfo查看帧时间。- Profile GPU Rendering(柱状图:绿色好,红色 Jank)。
5. SurfaceFlinger 与 合成(Composition)
每个 Window(Activity、Dialog、SurfaceView)对应一个 Surface(生产者)。
- App 渲染好 Buffer 后入队。
- SurfaceFlinger(系统服务)作为消费者,拉取所有可见 Surface 的 Buffer。
- HWC 决定:哪些 Layer 用硬件叠加(省电、省 GPU),哪些用 GPU 合成。
为什么重要?
- 多个 App/Window 叠加时,SurfaceFlinger 负责最终合成。
- Overdraw:同一像素多次绘制 → 浪费(用 Hierarchy Viewer / GPU Inspector 检查)。
BufferQueue:生产者-消费者队列,支持异步、Triple Buffer 等模式,避免撕裂。
6. 特殊组件:SurfaceView vs TextureView
- SurfaceView:独立 Surface,由 SurfaceFlinger 合成。适合游戏、视频(独立线程渲染,不影响 UI Thread)。
- TextureView:嵌入 View 层级,用 GLES 合成。灵活但可能增加 Overdraw。
动画对比:
- SurfaceView:像一个“洞”,下面独立渲染,SurfaceFlinger 直接叠加。
- TextureView:像一张“贴纸”,内容先渲染到纹理,再和其他 View 一起画。
7. 现代演进(Android 12+ / Jetpack Compose)
- BlastBufferQueue:优化 Buffer 提交。
- Jetpack Compose:类似 View,但用 Composition + Recomposition + Layout/Measure/Draw 阶段,更高效。
- Vulkan:更低开销的后端,未来趋势。
- High Refresh Rate:动态刷新率,Choreographer 适配 90/120Hz。
8. 开发者优化 Checklist(实战)
- 减少 Layout:用 ConstraintLayout,避免嵌套;数据变化用
invalidate()而非requestLayout()。 - 优化 onDraw:缓存 Paint/Path;用
Canvas.save()/restore()谨慎。 - 异步绘制:复杂内容用
SurfaceView或RenderScript/GLSurfaceView。 - 监控工具:
- Layout Inspector
- GPU Inspector / systrace
Choreographer.FrameCallback
- 避免:主线程 IO、大量对象创建、透明 View 叠加(Overdraw)。
- 测试:不同 GPU Renderer、不同刷新率设备。
总结
安卓渲染原理本质是**“生产 Buffer → 同步 VSync → 渲染 → 合成 → 显示”** 的严谨流水线。理解它,能帮你写出更丝滑的 App,快速定位卡顿根源。
一句话记忆:UI Thread 准备,RenderThread 画,SurfaceFlinger 合成,VSync 指挥一切。