Choreographer
Choreographer 深度解析
一、Choreographer 核心概念
Choreographer 是 Android 系统中协调动画、输入和绘制时序的关键组件,它通过 VSYNC 信号来同步 UI 操作。
1. 核心职责
- 帧同步:协调应用与显示刷新率(通常60Hz)
- 回调调度:管理以下回调类型的执行时序:
CALLBACK_INPUT
(输入事件)CALLBACK_ANIMATION
(动画)CALLBACK_INSETS_ANIMATION
(插入动画)CALLBACK_TRAVERSAL
(视图遍历/绘制)CALLBACK_COMMIT
(帧提交)
2. VSYNC 机制
// 简化的VSYNC请求流程
Choreographer.getInstance().postFrameCallback(new FrameCallback() {@Overridepublic void doFrame(long frameTimeNanos) {// 在下一个VSYNC信号时执行}
});
二、关键源码解析(基于Android 13)
1. 初始化流程
// 单例获取
public static Choreographer getInstance() {return getInstance(Looper.myLooper());
}private static final ThreadLocal<Choreographer> sThreadInstance =new ThreadLocal<Choreographer>() {@Overrideprotected Choreographer initialValue() {Looper looper = Looper.myLooper();return new Choreographer(looper, VSYNC_SOURCE_APP);}};
2. 回调队列管理
// 回调类型定义
private static final int CALLBACK_INPUT = 0;
private static final int CALLBACK_ANIMATION = 1;
// ...其他类型// 使用CallbackQueue数组管理不同优先级队列
private final CallbackQueue[] mCallbackQueues;
3. 帧回调处理
void doFrame(long frameTimeNanos, int frame) {// 1. 计算掉帧情况final long jitterNanos = frameTimeNanos - mLastFrameTimeNanos;if (jitterNanos >= mFrameIntervalNanos) {final long skippedFrames = jitterNanos / mFrameIntervalNanos;if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {Log.i(TAG, "Skipped " + skippedFrames + " frames! ");}}// 2. 按顺序执行各阶段回调doCallbacks(CALLBACK_INPUT, frameTimeNanos);doCallbacks(CALLBACK_ANIMATION, frameTimeNanos);doCallbacks(CALLBACK_INSETS_ANIMATION, frameTimeNanos);doCallbacks(CALLBACK_TRAVERSAL, frameTimeNanos);doCallbacks(CALLBACK_COMMIT, frameTimeNanos);
}
三、高级应用技巧
1. 精确帧率监控
class FrameMonitor : Choreographer.FrameCallback {private var lastFrameTime = 0Lprivate val choreographer = Choreographer.getInstance()override fun doFrame(frameTimeNanos: Long) {val currentTime = System.currentTimeMillis()if (lastFrameTime > 0) {val frameTime = currentTime - lastFrameTimeif (frameTime > 16) { // 60Hz下每帧应≈16.67msLog.w("FrameDrop", "Frame delayed: ${frameTime}ms")}}lastFrameTime = currentTimechoreographer.postFrameCallback(this)}
}
2. 自定义动画调度
// 创建高优先级动画调度器
public void scheduleAnimation(Animator animator) {Choreographer.getInstance().postCallback(Choreographer.CALLBACK_ANIMATION,() -> animator.doAnimationFrame(Choreographer.getInstance().getFrameTime()),null);
}
3. 性能优化实践
优化点1:减少Traversal回调负担
// 避免在绘制阶段做耗时操作
view.doOnPreDraw {// 轻量级操作post {// 耗时操作延后执行heavyOperation()}
}
优化点2:批量更新动画
// 合并多个属性动画到单个回调
ValueAnimator.setFrameDelay(0); // 使用系统默认帧率
Choreographer.getInstance().postFrameCallback(frameTime -> {animatorSet1.doTrame(frameTime);animatorSet2.doTrame(frameTime);
});
四、Choreographer 工作流程图
五、常见问题解决方案
1. 主线程卡顿检测
fun setupFrameMonitor() {val handler = Handler(Looper.getMainLooper())val monitor = object : Runnable {override fun run() {val start = SystemClock.uptimeMillis()Choreographer.getInstance().postFrameCallback {val cost = SystemClock.uptimeMillis() - startif (cost > 50) { // 阈值可根据需求调整reportJank(cost)}}handler.postDelayed(this, 1000) // 每秒检测一次}}handler.post(monitor)
}
2. 动画掉帧优化
// 使用SurfaceView替代普通View进行复杂动画
surfaceHolder.lockCanvas().apply {// 在此直接绘制surfaceHolder.unlockCanvasAndPost(this)
}// 通过Choreographer控制帧率
fun startCustomAnimation() {val choreographer = Choreographer.getInstance()val callback = object : Choreographer.FrameCallback {override fun doFrame(frameTimeNanos: Long) {updateAnimation(frameTimeNanos)choreographer.postFrameCallback(this) // 维持动画循环}}choreographer.postFrameCallback(callback)
}
六、平台差异说明
特性 | Android 4.1 (Jelly Bean) | Android 5.0 (Lollipop) | Android 12+ |
---|---|---|---|
VSYNC 同步 | 引入Project Butter | 支持三重缓冲 | 动态刷新率支持 |
回调类型 | 基础3种类型 | 增加INSETS类型 | 新增COMMIT阶段 |
帧延迟检测 | 简单日志警告 | 完善的Jank统计 | 集成到Perfetto |
掌握Choreographer的工作原理,可以帮助开发者:
- 构建更流畅的UI体验
- 精准定位性能瓶颈
- 实现自定义动画引擎
- 优化应用功耗表现