}
…
}
并不是每个垂直同步信号都会被上层订阅并处理,只有当
Choreographer
订阅了下一个垂直同步信号,SurfaceFlinger
才会把信号通过onVsync()
回调给上层。
图中第一个垂直信号到来之前,上层调用了postCallback()
向Choreographer
抛绘制任务,同时订阅了下一个信号并把mFrameScheduled
置为 true,表示需要绘制下一帧。当第一个信号产生时,onVsync()
被回调,同时将doFrame()
抛到主线程执行,执行完毕后将mFrameScheduled
置为 false,因没有后续订阅动作,所以上层不会收到后续的onVsync()
回调,也不会绘制任何新东西。
ViewRootImpl
向Choreographer
抛绘制任务后,任务并没有立马执行,而是被暂存在绘制任务链中,并注册接收下一个垂直同步信号。只有当下一个信号通过onVsync()
回调后,它才会被执行:
public final class Choreographer {
// 垂直同步信号接收器
private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
@Override
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
…
// 发送异步消息到主线程,执行当前的Runnable,即doFrame()
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
// 绘制一帧的内容
doFrame(mTimestampNanos, mFrame);
}
}
}
每当垂直同步信号回调时,都会向主线程推送一个待执行的绘制帧任务
doFrame()
。
public final class Choreographer {
void doFrame(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
// 如果没有订阅这一帧的垂直同步信号,则直接退出不绘制
if (!mFrameScheduled) {
return; // no work to do
}
…
try {
// 处理这一帧的输入事件
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
// 处理这一帧的动画
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
// 处理这一帧的 View 树遍历
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
// 所有绘制任务结束后执行 COMMIT 任务
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
} finally {
…
}
…
}
}
绘制每一帧时,会按照“输入事件”、“动画”、“View 树遍历”、“COMMIT”这样的顺序处理任务。
处理函数doCallback()
定义如下:
public final class Choreographer {
// 暂存绘制任务的链式数组
private final CallbackQueue[] mCallbackQueues;<