Choreographer实现机制_源码分析

一.使用
If your application does its rendering in a different thread, possibly using GL, or does not use the animation framework or view hierarchy at all and you want to ensure that it is appropriately synchronized with the display, then use postFrameCallback(Choreographer.FrameCallback).




二.源码分析
1.public void postFrameCallback(FrameCallback callback) { // 入口 在主线程Handler中执行一帧的操作


    // 三种CallBack类型
    // Callback type: Input callback.  Runs first.
    public static final int CALLBACK_INPUT = 0;


// Callback type: Animation callback.  Runs before traversals.
    public static final int CALLBACK_ANIMATION = 1;


    // Callback type: Traversal callback.  Handles layout and draw.  Runs last
    // after all other asynchronous messages have been handled.
    public static final int CALLBACK_TRAVERSAL = 2;


    private static final int CALLBACK_LAST = CALLBACK_TRAVERSAL; // 2


    private Choreographer(Looper looper) {
        mLooper = looper;
        mHandler = new FrameHandler(looper);
        mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
        mLastFrameTimeNanos = Long.MIN_VALUE;


        mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());


        mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1]; // 一开始就新建三种回调的队列
        for (int i = 0; i <= CALLBACK_LAST; i++) {
            mCallbackQueues[i] = new CallbackQueue();
        }
    }

// Posts a frame callback to run on the next frame.
// The callback runs once then is automatically removed.
public void postFrameCallback(FrameCallback callback) { // 入口
postFrameCallbackDelayed(callback, 0);
}


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

private final CallbackQueue[] mCallbackQueues;

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

final long now = SystemClock.uptimeMillis(); // Returns milliseconds since boot, 
final long dueTime = now + delayMillis;

// 把当前回调添加到回调队列. callbackType==CALLBACK_ANIMATION==1 添加到CALLBACK_ANIMATION这种类型的队列中
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);


if (dueTime <= now) {
scheduleFrameLocked(now); // 执行这里
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}

}

private final FrameHandler mHandler;
private void scheduleFrameLocked(long now) { // 执行一帧任务
if (!mFrameScheduled) { // mFrameScheduled默认为false
mFrameScheduled = true;

...
final long nextFrameTime = Math.max( // 计算下一帧的时间=上一帧时间+帧间隔(默认10ms)
mLastFrameTimeNanos / NANOS_PER_MS + sFrameDelay, now);
if (DEBUG) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
// 发送执行一帧的Message给Handler
Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
mHandler.sendMessageAtTime(msg, nextFrameTime); // 下一帧时间到来的时候发送message(延迟发送)
}
}

private final class FrameHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_FRAME: // 执行帧回调
doFrame(System.nanoTime(), 0);//
break;
case MSG_DO_SCHEDULE_VSYNC:
doScheduleVsync();
break;
case MSG_DO_SCHEDULE_CALLBACK:
doScheduleCallback(msg.arg1);
break;
}
}
}

// 核心方法 
void doFrame(long frameTimeNanos, int frame) { // 真正的执行一帧的操作
...


mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos; // 当前帧的时间

// 执行三个回调队列中已经超时的回调方法
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
}

void doCallbacks(int callbackType, long frameTimeNanos) {
CallbackRecord callbacks;

final long now = SystemClock.uptimeMillis();
// 返回所有到时间点的回调队列中的所有回调接口
callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(now);

mCallbacksRunning = true;


for (CallbackRecord c = callbacks; c != null; c = c.next) {
c.run(frameTimeNanos); // 执行用户传入的回调方法
}
}

总结:
1.执行的过程:用户传入一个回调接口给postFrameCallback函数,该函数在一个时刻(该函数是立刻执行的),发送Message到主线程
的Handler,Handler执行该回调接口对应的方法(在主线程中调用)

经过:回调接口插入到回调队列中mCallbackQueues[callbackType].addCallbackLocked(三个回调队列之一)-->执行一帧任务scheduleFrameLocked-->
发送执行一帧的Message给Handler:mHandler.sendMessageAtTime(msg, nextFrameTime)-->Handler执行一帧操作:doFrame(System.nanoTime(), 0);
-->从三个回调队列中取出时间到的所有回调接口,并执行:doCallbacks-->执行用户传递进来的回调接口CallbackRecord.run(frameTimeNanos)//核心

2.Choreographer维护主要数据:--->再一次说明数据才是王道!!
private final FrameHandler mHandler; // Handler
    private final CallbackQueue[] mCallbackQueues; // 三个回调队列







/补充///
/*
回调队列CallbackQueue队列,保存CallbackRecord
队列按照时间顺序排序:时间最小的排在最前面
队列的操作:添加一个回调记录,移除一个回调记录,查找一个回调记录
*/
    private final class CallbackQueue {
        private CallbackRecord mHead; // 保存时间最小的那个item(最早要发生的)


        public boolean hasDueCallbacksLocked(long now) { // Due适当的,应有的
            return mHead != null && mHead.dueTime <= now;
        }


        public CallbackRecord extractDueCallbacksLocked(long now) { //extract提取
            CallbackRecord callbacks = mHead;
            if (callbacks == null || callbacks.dueTime > now) {
                return null;
            }


            CallbackRecord last = callbacks;
            CallbackRecord next = last.next;
            while (next != null) {
                if (next.dueTime > now) {
                    last.next = null;
                    break;
                }
                last = next;
                next = next.next;
            }
            mHead = next;
            return callbacks;
        }


        public void addCallbackLocked(long dueTime, Object action, Object token) {
            CallbackRecord callback = obtainCallbackLocked(dueTime, action, token);
            CallbackRecord entry = mHead;
            if (entry == null) {
                mHead = callback;
                return;
            }
            if (dueTime < entry.dueTime) { // 按照时间顺序从小到大排列
                callback.next = entry;
                mHead = callback;
                return;
            }
            while (entry.next != null) {
                if (dueTime < entry.next.dueTime) {
                    callback.next = entry.next;
                    break;
                }
                entry = entry.next;
            }
            entry.next = callback;
        }


        public void removeCallbacksLocked(Object action, Object token) {
            CallbackRecord predecessor = null;
            for (CallbackRecord callback = mHead; callback != null;) {
                final CallbackRecord next = callback.next;
                if ((action == null || callback.action == action)
                        && (token == null || callback.token == token)) {
                    if (predecessor != null) {
                        predecessor.next = next;
                    } else {
                        mHead = next;
                    }
                    recycleCallbackLocked(callback);
                } else {
                    predecessor = callback;
                }

                callback = next;
            }
        }
    }

/*
回调记录
*/
private static final class CallbackRecord {
        public CallbackRecord next;
        public long dueTime;
        public Object action; // Runnable or FrameCallback
        public Object token;


        public void run(long frameTimeNanos) {
            if (token == FRAME_CALLBACK_TOKEN) { // FrameCallback接口--接口函数为帧
                ((FrameCallback)action).doFrame(frameTimeNanos);
            } else { // Runnable接口
                ((Runnable)action).run();
            }
        }
    }

   public interface FrameCallback {
// Called when a new display frame is being rendered.
public void doFrame(long frameTimeNanos);
}






--------------------------------------------------------------------------------
入口2: postCallback分析
// ValueAnimator.java:mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null);// action为下面run函数
public void postCallback(int callbackType, Runnable action, Object token) {
        postCallbackDelayed(callbackType, action, token, 0);
    }

public void postCallbackDelayed(int callbackType,
            Runnable action, Object token, long delayMillis) {
// 该函数在上面有分析,此处忽略.之后执行代码同上:回调传入的action(run方法)
        postCallbackDelayedInternal(callbackType, action, token, delayMillis);
    }












  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值