其中**CALLBACK\_ANIMATION**是处理动画相关的逻辑,而**CALLBACK\_TRAVERSAL**则会调用到ViewRootImpl的**performTraversals()** 函数,从而执行到我们所熟悉的View的measure、layout、draw三大流程。
所以可以说,**doFrame()** 函数包含了应用层绘制一帧的逻辑处理。

由于Choreographer处于如此重要的一个位置,基本上所有的卡顿监控都会围绕着Choreographer进行的,除了自带的掉帧计算,Choreographer 提供的 FrameCallback 和 FrameInfo都是应用层可以直接访问的接口。
下面介绍一下市面上开源方案的几种实现方式和简单对比。
### 1 Choreographer的FrameCallback
**TinyDancer** 就是通过这种方式计算出FPS。 核心代码:
Choreographer.getInstance().postFrameCallback(object : Choreographer.FrameCallback {
override fun doFrame(frameTimeNanos: Long) {
if (lastFrameTimeNanos > 0) {
val frameTime = (frameTimeNanos - lastFrameTimeNanos) / NANOS_PER_MS
}
lastFrameTimeNanos = frameTimeNanos
Choreographer.getInstance().postFrameCallback(this)
}
})
通过记录doFrame回调的间隔时间作为每帧耗时frameTime,如此也很容易计算出FPS=1000/frameTime,掉帧数=frameTime/16.6。
### 2 Choreographer + Looper
Tencent/**matrix** 虽然也是基于Choreographer,但其监测FPS的机制和上面的FrameCallback方案不太一样。 由前面Choreographer的介绍可知,所谓每一帧其实指的就是input、animation、traversal三种事件对应的三个doCallback方法的执行结果,而matrix统计帧耗时就是通过监测这三个方法的执行总时间来表示。matrix监测FPS的主要实现在`LooperMonitor`和`UIThreadMoniter`两个类里。
1. `LooperMonitor`为主线程Looper设置一个Printer来监听UI线程每个Message的开始、结束,从而得到Message的执行耗时。(方案同 **BlockCanary** )
class LooperPrinter implements Printer {
@Override
public void println(String x) {
…
dispatch(x.charAt(0) == ‘>’, x);
}
private void dispatch(boolean isBegin, String log) {
for (LooperDispatchListener listener : listeners) {
if (isBegin) {
listener.onDispatchStart(log);
} else {
listener.onDispatchEnd(log);
}
}
}
}
2. `UIThreadMoniter`通过java反射向Choreographer的CALLBACK\_INPUT、CALLBACK\_ANIMATION、CALLBACK\_TRAVERSAL三个事件的callback队列的**头部**插入自定义callback。
//UIThreadMonitor.java
@Override
public void run() {
doFrameBegin(token);
doQueueBegin(CALLBACK_INPUT<