Choreography 的 callback

221 阅读2分钟

1. 作用

当 vsync 信号来临时执行相应逻辑

2. 数据结构

1. 单个 callback

private static final class CallbackRecord {
    public CallbackRecord next;
    public long dueTime;
    public Object action;
    public Object token;
}

next : 链表形式,指向下一个同类型的 callback

dueTime : 最晚执行时间

action :可以是以下 3 种类型

  1. Runnable: 无参 task
public interface Runnable {
    public abstract void run();
}
public void postCallback(int callbackType, Runnable action, Object token) 
  1. FrameCallback: 参数为 long 的 task
public interface FrameCallback {
    public void doFrame(long frameTimeNanos);
}
public void postFrameCallback(FrameCallback callback) 
  1. VsyncCallback : 参数为 FrameData 的 task
public interface VsyncCallback {
    void onVsync(@NonNull FrameData data);
}
void postVsyncCallback(@NonNull VsyncCallback callback)

token:

private static final Object FRAME_CALLBACK_TOKEN = new Object() {
    public String toString() { return "FRAME_CALLBACK_TOKEN"; }
};
private static final Object VSYNC_CALLBACK_TOKEN = new Object() {
    public String toString() {
        return "VSYNC_CALLBACK_TOKEN";
    }
};

token作用:CallbackRecord 执行 action 的时候,需要根据 token 不同,来强制转换成不同的类型

public void run(long frameTimeNanos) {
   if (token == FRAME_CALLBACK_TOKEN) {
       ((FrameCallback)action).doFrame(frameTimeNanos);
   } else {
       ((Runnable)action).run();
   }
}

void run(FrameData frameData) {
   frameData.setInCallback(true);
   if (token == VSYNC_CALLBACK_TOKEN) {
       ((VsyncCallback) action).onVsync(frameData);
   } else {
       run(frameData.getFrameTimeNanos());
   }
   frameData.setInCallback(false);
}

2. callback 队列

private final class CallbackQueue {
    private CallbackRecord mHead;
    public void addCallbackLocked(long dueTime, Object action, Object token)boolean hasDueCallbacksLocked(long now);
    CallbackRecord extractDueCallbacksLocked(long now)
    public void removeCallbacksLocked(Object action, Object token);
}

专门管理 CallbackRecord 的数据结构:

mHead 指向第一个 CallbackRecord,进而可以对 callback 队列进行增删查改

3. callback 声明:

private final CallbackQueue[] mCallbackQueues;
mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++) {
    mCallbackQueues[i] = new CallbackQueue();
}
  1. 是个数组
  2. 每个索引处存放不同类型的 callback 队列(CallbackQueue)

callback 类型:

//事件类型
public static final int CALLBACK_INPUT = 0;
//动画类型处理动画的最终显示结果
public static final int CALLBACK_ANIMATION = 1;
//一个动画可能有多个动画复合而成,这个类型主要处理这类
public static final int CALLBACK_INSETS_ANIMATION = 2;
//界面的布局刷新
public static final int CALLBACK_TRAVERSAL = 3;
//app 暂时不管
public static final int CALLBACK_COMMIT = 4;

private static final int CALLBACK_LAST = CALLBACK_COMMIT;

4. app 使用接口

public void postFrameCallback(FrameCallback callback) {
    postFrameCallbackDelayed(callback, 0);
}

public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
            callback, FRAME_CALLBACK_TOKEN, delayMillis);
}

public void postVsyncCallback(@NonNull VsyncCallback callback) {
}

1.callback 的添加

private void postCallbackDelayedInternal(int callbackType,
        Object action, Object token, long delayMillis) {

    synchronized (mLock) {
        final long now = SystemClock.uptimeMillis();
        final long dueTime = now + delayMillis;
        mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
        
        //超过最晚时间马上执行
        if (dueTime <= now) {
            scheduleFrameLocked(now);
            //扔到 handler 消息队列中,等待执行
        } else {
            Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
            msg.arg1 = callbackType;
            msg.setAsynchronous(true);
            mHandler.sendMessageAtTime(msg, dueTime);
        }
    }
}

2. callback 执行:按照如下顺序

doCallbacks(Choreographer.CALLBACK_INPUT, frameIntervalNanos);

doCallbacks(Choreographer.CALLBACK_ANIMATION, frameIntervalNanos);

doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameIntervalNanos);

doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameIntervalNanos);

doCallbacks(Choreographer.CALLBACK_COMMIT, frameIntervalNanos);