前言
在 Compose 开发中,我们习惯了状态改变引发重组。但你有没有想过:状态改变的那一刻,到屏幕像素闪烁的那一刻,中间到底发生了什么?
Compose 并不是在 State 改变时立刻重画,它在等待一个信号。这个信号的发出者,就是 Android 系统的“编舞者” —— Choreographer。
今天,我们从底层理清 Compose 是如何与系统步调一致的。
一、 VSync:显示系统的“心跳”
显示器有一个固定的刷新频率(如 60Hz 或 120Hz)。每一帧开始时,系统会发出一个 VSync(垂直同步信号)。
- 如果不听 VSync 的话:App 可能会在显示器画到一半时提交新数据,导致产生撕裂(Tearing)。
二、 Choreographer 的角色:物流调度员
Choreographer 的核心职责是:协调(Coordinate)动画、输入和绘制的节奏。
当你在 Compose 里改了一个 count++:
- 快照通知:Compose 的快照系统感知到变化。
- 注册回调:Compose 通过
Owner接口(AndroidComposeView)向Choreographer发起申请:“下一帧 VSync 来的时候,请叫我一下(postFrameCallback)”。 - 进入等待:此时主线程可以去干别的。
三、 节奏响起:当 VSync 信号到达
当信号通过底层 Socket 传回应用进程时:
- Choreographer 觉醒:它从
native层被唤醒。 - 回调队列执行:它按顺序处理四种任务:
- INPUT(输入处理)
- ANIMATION(动画执行)
- TRAVERSAL(传统 View 树测量布局)
- COMMIT(最后提交)
- Compose 介入:Compose 的重组逻辑就挂载在 ANIMATION 或 TRAVERSAL 阶段。此时
Recomposer启动,执行真正的逻辑运算。
四、 为什么理解它对性能优化至关重要?
作为十年老兵,你应该能通过这个原理分析出卡顿的真凶:
- 主线程耗时过长:如果在 VSync 到达时,主线程正在执行一个耗时的循环,
Choreographer无法及时响应回调。- 现象:这就是所谓的“跳帧”。屏幕会显示上一帧的内容,等待下一轮心跳。
- Compose 的智能合并:如果你在一帧的时间(16ms)内连续改了 10 次状态,
Choreographer只会触发一次回调。Compose 会在这一次回调里合并所有变更,只重组一次。
五、 给资深开发的源码指引
如果你想实地考察,请在 Android 源码中搜索:
android.view.Choreographer:观察postFrameCallback方法。androidx.compose.ui.platform.AndroidComposeView:搜索Choreographer的引用,看它如何申请刷新。
结语
理解了 Choreographer,你就明白了 Compose 的“律动”来源。它不是一个孤立的 UI 库,它是系统节拍下的精密舞蹈。
下一篇,我们将探讨像素的传递网 —— BufferQueue 与 SurfaceFlinger:像素的“接力赛”。