Android 渲染原理

高桥凉介
分享互动规则

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 源码文档):

Android Graphics Pipeline

动画说明(想象这个图动起来):

  • 左侧多个 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)

  1. Measure(测量):自顶向下,父 View 给子 View 约束(MeasureSpec: EXACTLY / AT_MOST / UNSPECIFIED),子 View 计算期望尺寸。
  2. Layout(布局):自顶向下,父 View 决定子 View 的具体位置(left/top/right/bottom)。
  3. 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+):

  1. VSync 到来 → Choreographer 回调。
  2. Input 处理 → Animation → Measure/Layout/Draw(UI Thread)。
  3. RenderThread 渲染 → 提交 Buffer 到 SurfaceFlinger。
  4. 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(实战)

  1. 减少 Layout:用 ConstraintLayout,避免嵌套;数据变化用 invalidate() 而非 requestLayout()
  2. 优化 onDraw:缓存 Paint/Path;用 Canvas.save()/restore() 谨慎。
  3. 异步绘制:复杂内容用 SurfaceViewRenderScript / GLSurfaceView
  4. 监控工具
    • Layout Inspector
    • GPU Inspector / systrace
    • Choreographer.FrameCallback
  5. 避免:主线程 IO、大量对象创建、透明 View 叠加(Overdraw)。
  6. 测试:不同 GPU Renderer、不同刷新率设备。

总结

安卓渲染原理本质是**“生产 Buffer → 同步 VSync → 渲染 → 合成 → 显示”** 的严谨流水线。理解它,能帮你写出更丝滑的 App,快速定位卡顿根源。

一句话记忆UI Thread 准备,RenderThread 画,SurfaceFlinger 合成,VSync 指挥一切

评论 1

支持 @用户名 提醒对方(需为站内已注册用户名);回复仅支持一层楼中楼。

登录后发表评论、回复与 @ 提及。

举报

举报会匿名发送给管理员审核。

  • 高桥凉介 · 2026/5/15 01:32:21

    写的,挺好的

码谱 · The Digital Atelier · 技术内容社区

下载 Android 版

下载完成后,点击通知栏中的安装包完成安装