Framework 补完计划 (1):Choreographer —— 驱动 Compose 重组的幕后“节拍器”

64 阅读2分钟

前言

在 Compose 开发中,我们习惯了状态改变引发重组。但你有没有想过:状态改变的那一刻,到屏幕像素闪烁的那一刻,中间到底发生了什么?

Compose 并不是在 State 改变时立刻重画,它在等待一个信号。这个信号的发出者,就是 Android 系统的“编舞者” —— Choreographer

今天,我们从底层理清 Compose 是如何与系统步调一致的。


一、 VSync:显示系统的“心跳”

显示器有一个固定的刷新频率(如 60Hz 或 120Hz)。每一帧开始时,系统会发出一个 VSync(垂直同步信号)

  • 如果不听 VSync 的话:App 可能会在显示器画到一半时提交新数据,导致产生撕裂(Tearing)。

二、 Choreographer 的角色:物流调度员

Choreographer 的核心职责是:协调(Coordinate)动画、输入和绘制的节奏。

当你在 Compose 里改了一个 count++

  1. 快照通知:Compose 的快照系统感知到变化。
  2. 注册回调:Compose 通过 Owner 接口(AndroidComposeView)向 Choreographer 发起申请:“下一帧 VSync 来的时候,请叫我一下(postFrameCallback)”。
  3. 进入等待:此时主线程可以去干别的。

三、 节奏响起:当 VSync 信号到达

当信号通过底层 Socket 传回应用进程时:

  1. Choreographer 觉醒:它从 native 层被唤醒。
  2. 回调队列执行:它按顺序处理四种任务:
    • INPUT(输入处理)
    • ANIMATION(动画执行)
    • TRAVERSAL(传统 View 树测量布局)
    • COMMIT(最后提交)
  3. Compose 介入:Compose 的重组逻辑就挂载在 ANIMATIONTRAVERSAL 阶段。此时 Recomposer 启动,执行真正的逻辑运算。

四、 为什么理解它对性能优化至关重要?

作为十年老兵,你应该能通过这个原理分析出卡顿的真凶:

  1. 主线程耗时过长:如果在 VSync 到达时,主线程正在执行一个耗时的循环,Choreographer 无法及时响应回调。
    • 现象:这就是所谓的“跳帧”。屏幕会显示上一帧的内容,等待下一轮心跳。
  2. Compose 的智能合并:如果你在一帧的时间(16ms)内连续改了 10 次状态,Choreographer 只会触发一次回调。Compose 会在这一次回调里合并所有变更,只重组一次。

五、 给资深开发的源码指引

如果你想实地考察,请在 Android 源码中搜索:

  • android.view.Choreographer:观察 postFrameCallback 方法。
  • androidx.compose.ui.platform.AndroidComposeView:搜索 Choreographer 的引用,看它如何申请刷新。

结语

理解了 Choreographer,你就明白了 Compose 的“律动”来源。它不是一个孤立的 UI 库,它是系统节拍下的精密舞蹈。

下一篇,我们将探讨像素的传递网 —— BufferQueue 与 SurfaceFlinger:像素的“接力赛”