Android系统的编舞者Choreographer

前言

上一篇文章 Android的16ms和垂直同步以及三重缓存 解释了手机流畅性的问题,并在文章中提到了在Android4.1中添加的VsyncChoreographer机制,用于同Vsync机制配合,实现统一调度界面绘图。

1、Choreographer的构造

Choreographer是线程级别的单例,并且具有处理当前线程消息循环队列的功能。

public final class Choreographer {
    // Enable/disable vsync for animations and drawing.
    private static final boolean USE_VSYNC = SystemProperties.getBoolean(
            "debug.choreographer.vsync", true);
    
    //单例
    public static Choreographer getInstance() {
        return sThreadInstance.get();
    }

    //每个线程一个Choreographer实例
    private static final ThreadLocal<Choreographer> sThreadInstance =
            new ThreadLocal<Choreographer>() {
        @Override
        protected Choreographer initialValue() {
            Looper looper = Looper.myLooper();
            if (looper == null) {
                throw new IllegalStateException("The current thread must have a looper!");
            }
            return new Choreographer(looper);
        }
    };

    private Choreographer(Looper looper) {
        mLooper = looper;
        //创建handle对象,用于处理消息,其looper为当前的线程的消息队列
        mHandler = new FrameHandler(looper);
        //创建VSYNC的信号接受对象
        mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
        //初始化上一次frame渲染的时间点
        mLastFrameTimeNanos = Long.MIN_VALUE;
        //计算帧率,也就是一帧所需的渲染时间,getRefreshRate是刷新率,一般是60
        mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
        //创建消息处理队列
        mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
        for (int i = 0; i <= CALLBACK_LAST; i++) {
            mCallbackQueues[i] = new CallbackQueue();
        }
    }
}

变量USE_VSYNC用于表示系统是否是用了Vsync同步机制,该值是通过读取系统属性debug.choreographer.vsync来获取的。如果系统使用了Vsync同步机制,则创建一个FrameDisplayEventReceiver对象用于请求并接收Vsync事件,最后Choreographer创建了一个大小为3的CallbackQueue队列数组,用于保存不同类型的Callback。

2、Choreographer的使用

2.1、注册Runnable对象

作者之前写过一篇关于ViewRootImpl的文章:ViewRootImpl的独白,我不是一个View(布局篇)里面有涉及使用Choreographer进行View的绘制,这次我们从ViewRootImpl的绘制出发来看看Choreographer的使用。

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    Choreographer mChoreographer;
    /***部分代码省略***/
    public ViewRootImpl(Context context, Display display) {
        /***部分代码省略***/
        mChoreographer = Choreographer.getInstance();
        /***部分代码省略***/
    }
    /***部分代码省略***/
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
        }
    }
}

2.1、注册FrameCallback对象

无论是注册Runnable还是注册FrameCallback对象最终都会调用postCallbackDelayedInternal方法往mCallbackQueues添加回调,区别在于FrameCallback的token为FRAME_CALLBACK_TOKEN,两者在回调的时候不相同。

public final class Choreographer {
    // All frame callbacks posted by applications have this token.
    private static final Object FRAME_CALLBACK_TOKEN = new Object() {
        public String toString() { return "FRAME_CALLBACK_TOKEN"; }
    };

    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)action).doFrame(frameTimeNanos);
            } else {
                ((Runnable)action).run();
            }
        }
    }
}

3、Choreographer的消息处理

3.1、Choreographer接受消息

public final class Choreographer {
    //Input callback.  Runs first.
    public static final int CALLBACK_INPUT = 0;
    //Animation callback.  Runs before traversals.
    public static final int CALLBACK_ANIMATION = 1;
    // 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;

    //长度为3(CALLBACK_LAST+1)的CallbackQueue类型的数组
    private final CallbackQueue[] mCallbackQueues;

    //发送回调事件
    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) {
        if (action == null) {
            throw new IllegalArgumentException("action must not be null");
        }
        if (callbackType < 0 || callbackType > CALLBACK_LAST) {
            throw new IllegalArgumentException("callbackType is invalid");
        }

        postCallbackDelayedInternal(callbackType, action, token, delayMillis);
    }

    private void postCallbackDelayedInternal(int callbackType,
            Object action, Object token, long delayMillis) {
        /***部分代码省略***/
        synchronized (mLock) {
            //从开机到现在的毫秒数(手机睡眠的时间不包括在内); 
            final long now = SystemClock.uptimeMillis();
            final long dueTime = now + delayMillis;
            //添加类型为callbackType的CallbackQueue(将要执行的回调封装而成)
            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);
            }
        }
    }
    /**
     * @param dueTime 任务开始时间
     * @param action 任务
     * @param token 标识
     */
    private CallbackRecord obtainCallbackLocked(long dueTime, Object action, Object token) {
        CallbackRecord callback = mCallbackPool;
        if (callback == null) {
            callback = new CallbackRecord();
        } else {
            mCallbackPool = callback.next;
            callback.next = null;
        }
        callback.dueTime = dueTime;
        callback.action = action;
        callback.token = token;
        return callback;
    }
    private final class CallbackQueue {
        private CallbackRecord mHead;
        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;
        }
    }
}

3.1.1、CallbackQueue

public final class Choreographer {
    /**
     * Callback type: Input callback.  Runs first.
     * @hide
     */
    public static final int CALLBACK_INPUT = 0;

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

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

三种类型不同的CallbackRecord链表,按照任务触发时间由小到大排列。

CallbackQueue.png

3.2、FrameHandler异步处理

public final class Choreographer {

    private static final int MSG_DO_FRAME = 0;
    private static final int MSG_DO_SCHEDULE_VSYNC = 1;
    private static final int MSG_DO_SCHEDULE_CALLBACK = 2;
    private final class FrameHandler extends Handler {
        public FrameHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_DO_FRAME:
                    //刷新当前这一帧
                    doFrame(System.nanoTime(), 0);
                    break;
                case MSG_DO_SCHEDULE_VSYNC:
                    //做VSYNC的信号同步
                    doScheduleVsync();
                    break;
                case MSG_DO_SCHEDULE_CALLBACK:
                    //将当前任务加入执行队列
                    doScheduleCallback(msg.arg1);
                    break;
            }
        }
    }
}

3.2.1、doFrame

public final class Choreographer {
    void doFrame(long frameTimeNanos, int frame) {
        final long startNanos;
        synchronized (mLock) {
            if (!mFrameScheduled) {
                return; // no work to do
            }
            //当前时间
            startNanos = System.nanoTime();
            //抖动间隔
            final long jitterNanos = startNanos - frameTimeNanos;
            //抖动间隔大于屏幕刷新时间间隔(16ms)
            if (jitterNanos >= mFrameIntervalNanos) {
                final long skippedFrames = jitterNanos / mFrameIntervalNanos;
                //跳过了几帧!,也许当前应用在主线程做了太多的事情。
                if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
                    Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
                            + "The application may be doing too much work on its main thread.");
                }
                //最后一次的屏幕刷是lastFrameOffset之前开始的
                final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
                if (DEBUG) {
                    Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
                            + "which is more than the frame interval of "
                            + (mFrameIntervalNanos * 0.000001f) + " ms!  "
                            + "Skipping " + skippedFrames + " frames and setting frame "
                            + "time to " + (lastFrameOffset * 0.000001f) + " ms in the past.");
                }
                //最后一帧的刷新开始时间
                frameTimeNanos = startNanos - lastFrameOffset;
            }
            //由于跳帧可能造成了当前展现的是之前的帧,这样需要等待下一个vsync信号
            if (frameTimeNanos < mLastFrameTimeNanos) {
                if (DEBUG) {
                    Log.d(TAG, "Frame time appears to be going backwards.  May be due to a "
                            + "previously skipped frame.  Waiting for next vsync.");
                }
                scheduleVsyncLocked();
                return;
            }
            //当前画面刷新的状态置false
            mFrameScheduled = false;
            //更新最后一帧的刷新时间
            mLastFrameTimeNanos = frameTimeNanos;
        }
        //按照优先级策略进行画面刷新时间处理
        doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
        doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
        doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
        
        if (DEBUG) {
            final long endNanos = System.nanoTime();
            Log.d(TAG, "Frame " + frame + ": Finished, took "
                    + (endNanos - startNanos) * 0.000001f + " ms, latency "
                    + (startNanos - frameTimeNanos) * 0.000001f + " ms.");
        }
    }
}

3.2.2、doScheduleVsync

public final class Choreographer {
    //等待vsync信号
    void doScheduleVsync() {
        synchronized (mLock) {
            if (mFrameScheduled) {
                scheduleVsyncLocked();
            }
        }
    }
    //当运行在Looper线程,则立刻调度vsync
    private void scheduleVsyncLocked() {
        mDisplayEventReceiver.scheduleVsync();
    }
}

3.2.3、doScheduleCallback

public final class Choreographer {
    // Enable/disable vsync for animations and drawing.
    private static final boolean USE_VSYNC = SystemProperties.getBoolean(
            "debug.choreographer.vsync", true);
    private final class CallbackQueue {
        //判断是否有能执行的任务
        public boolean hasDueCallbacksLocked(long now) {
            return mHead != null && mHead.dueTime <= now;
        }
        /***部分代码省略***/
    }
    /***部分代码省略***/
    //执行任务回调
    void doScheduleCallback(int callbackType) {
        synchronized (mLock) {
            if (!mFrameScheduled) {
                final long now = SystemClock.uptimeMillis();
                //有能执行的任务
                if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {
                    scheduleFrameLocked(now);
                }
            }
        }
    }

    private void scheduleFrameLocked(long now) {
        if (!mFrameScheduled) {
            mFrameScheduled = true;
            if (USE_VSYNC) {
                if (DEBUG) {
                    Log.d(TAG, "Scheduling next frame on vsync.");
                }

                // If running on the Looper thread, then schedule the vsync immediately,
                // otherwise post a message to schedule the vsync from the UI thread
                // as soon as possible.
                if (isRunningOnLooperThreadLocked()) {
                    //当运行在Looper线程,则立刻调度vsync
                    scheduleVsyncLocked();
                } else {
                    //切换到主线程,调度vsync
                    Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtFrontOfQueue(msg);
                }
            } else {
                //如果没有VSYNC的同步,则发送消息刷新画面
                final long nextFrameTime = Math.max(
                        mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
                if (DEBUG) {
                    Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
                }
                Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, nextFrameTime);
            }
        }
    }
    //检测当前的Looper线程是不是主线程
    private boolean isRunningOnLooperThreadLocked() {
        return Looper.myLooper() == mLooper;
    }
}
public final class Choreographer {
    // The display event receiver can only be accessed by the looper thread to which
    // it is attached.  We take care to ensure that we post message to the looper
    // if appropriate when interacting with the display event receiver.
    private final FrameDisplayEventReceiver mDisplayEventReceiver;

    private Choreographer(Looper looper) {
        /***部分代码省略***/
        //在Choreographer的构造函数中,我们使用USE_VSYNC则会有FrameDisplayEventReceiver做为与显示器时间进行交互
        mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
    }
    /***部分代码省略***/
    private final class FrameDisplayEventReceiver extends DisplayEventReceiver
            implements Runnable {
        //构造函数需要传入当前的looper队列  
        public FrameDisplayEventReceiver(Looper looper) {
            super(looper);
        }
        /***部分代码省略***/  
    }
}
public abstract class DisplayEventReceiver {
    private static native void nativeScheduleVsync(long receiverPtr);
    /**
     * Creates a display event receiver.
     *
     * @param looper The looper to use when invoking callbacks.
     */
    public DisplayEventReceiver(Looper looper) {
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }
        mMessageQueue = looper.getQueue();
        //接受数量多少等于looper中消息的多少
        mReceiverPtr = nativeInit(this, mMessageQueue);
        mCloseGuard.open("dispose");
    }
    /**
     * Schedules a single vertical sync pulse to be delivered when the next
     * display frame begins.
     */
    public void scheduleVsync() {
        if (mReceiverPtr == 0) {
            Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
                    + "receiver has already been disposed.");
        } else {
            nativeScheduleVsync(mReceiverPtr);
        }
    }
}

3.3、Choreographer流程汇总

choreographer.png

4、native端的消息处理

文件路径:frameworks/base/core/jni/android_view_DisplayEventReceiver.cpp

4.1、NativeDisplayEventReceiver类结构

//NativeDisplayEventReceiver类的定义
class NativeDisplayEventReceiver : public LooperCallback {
public://对象公共方法
    //构造函数
    NativeDisplayEventReceiver(JNIEnv* env,
            jobject receiverObj, const sp<MessageQueue>& messageQueue);
    status_t initialize();  //初始化方法
    void dispose();
    status_t scheduleVsync();//获取下一个VSYNC信号

protected:
    virtual ~NativeDisplayEventReceiver();//析构函数

private:
    jobject mReceiverObjGlobal;//java层的DisplayEventReceiver的全局引用
    sp<MessageQueue> mMessageQueue;//looper的消息队列
    DisplayEventReceiver mReceiver;//frameworks/nivate/libs/gui/DisplayEventReceiver.cpp
    bool mWaitingForVsync;//默认为false

    virtual int handleEvent(int receiveFd, int events, void* data);
    bool processPendingEvents(nsecs_t* outTimestamp, int32_t* id, uint32_t* outCount);
    void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count);
    void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected);
};

//ststem/core/include/utils/Looper.h
/**
 * A looper callback.
 */
//NativeDisplayEventReceiver的父类,用与looper中消息的回调
class LooperCallback : public virtual RefBase {
protected:
    virtual ~LooperCallback() { }

public:
    virtual int handleEvent(int fd, int events, void* data) = 0;
};

4.2、NativeDisplayEventReceiver初始化

//初始化native的消息队列
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
        jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    //构造NativeDisplayEventReceiver对象
    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
            receiverObj, messageQueue);
    status_t status = receiver->initialize();
    if (status) {
        String8 message;
        message.appendFormat("Failed to initialize display event receiver.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
        return 0;
    }

    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
    return reinterpret_cast<jlong>(receiver.get());
}
//NativeDisplayEventReceiver的构造函数
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
        jobject receiverObj, const sp<MessageQueue>& messageQueue) :
        mReceiverObjGlobal(env->NewGlobalRef(receiverObj)),
        mMessageQueue(messageQueue), mWaitingForVsync(false) {
    ALOGV("receiver %p ~ Initializing input event receiver.", this);
}
//receiver内部数据的初始化
status_t NativeDisplayEventReceiver::initialize() {
    status_t result = mReceiver.initCheck();
    if (result) {
        ALOGW("Failed to initialize display event receiver, status=%d", result);
        return result;
    }
    //监听mReceiver的所获取的文件句柄。
    int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT,
            this, NULL);
    if (rc < 0) {
        return UNKNOWN_ERROR;
    }
    return OK;
}

4.3、NativeDisplayEventReceiver请求VSYNC的同步

//java层调用DisplayEventReceiver的scheduleVsync请求VSYNC的同步
static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
    sp<NativeDisplayEventReceiver> receiver =
            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
    status_t status = receiver->scheduleVsync();
    if (status) {
        String8 message;
        message.appendFormat("Failed to schedule next vertical sync pulse.  status=%d", status);
        jniThrowRuntimeException(env, message.string());
    }
}

status_t NativeDisplayEventReceiver::scheduleVsync() {
    if (!mWaitingForVsync) {
        ALOGV("receiver %p ~ Scheduling vsync.", this);

        // Drain all pending events.
        nsecs_t vsyncTimestamp;
        int32_t vsyncDisplayId;
        uint32_t vsyncCount;
        processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
        //请求下一次Vsync信息处理
        status_t status = mReceiver.requestNextVsync();
        if (status) {
            ALOGW("Failed to request next vsync, status=%d", status);
            return status;
        }

        mWaitingForVsync = true;
    }
    return OK;
}

//frameworks/native/libs/gui/DisplayEventReceiver.cpp
//通过IDisplayEventConnection接口来请求Vsync信号,IDisplayEventConnection实现了Binder通信框架,可以跨进程调用。
//因为Vsync信号请求进程和Vsync产生进程有可能不在同一个进程空间,因此这里就借助IDisplayEventConnection接口来实现。
status_t DisplayEventReceiver::requestNextVsync() {
    if (mEventConnection != NULL) {
        mEventConnection->requestNextVsync();
        return NO_ERROR;
    }
    return NO_INIT;
}

4.4、NativeDisplayEventReceiver处理消息

//NativeDisplayEventReceiver处理消息
int NativeDisplayEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    ...
    nsecs_t vsyncTimestamp;
    int32_t vsyncDisplayId;
    uint32_t vsyncCount;
    //过滤出最后一次的vsync
    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
        mWaitingForVsync = false;
        //分发Vsync,调用到native的android/view/DisplayEventReceiver.class的dispatchVsync方法
        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
    }
    return 1;
}

4.5、DisplayEventReceiver分发VSYNC信号

public abstract class DisplayEventReceiver {
    /***部分代码省略***/
    public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
    }
    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
        onVsync(timestampNanos, builtInDisplayId, frame);
    }
}

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) {
        //忽略来自第二显示屏的Vsync
        if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
            scheduleVsync();
            return;
        }
        /***部分代码省略***/
        mTimestampNanos = timestampNanos;
        mFrame = frame;
        //该消息的callback为当前对象FrameDisplayEventReceiver
        Message msg = Message.obtain(mHandler, this);
        msg.setAsynchronous(true);
        mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
    }

    @Override
    public void run() {
        mHavePendingVsync = false;
        //DisplayEventReceiver消息处理
        doFrame(mTimestampNanos, mFrame);
    }
}

4.6、DisplayEventReceiver消息处理

参见3.2.1、doFrame介绍

6、Choreographer处理回调

6.1、Choreographer触发可执行任务的回调

这里为什么说可执行任务呢?因为每个任务都有自己的触发时间,Choreographer只选择它能触发的任务。

public final class Choreographer {
    //进行回调的标识
    private boolean mCallbacksRunning;
    /***部分代码省略***/
    void doCallbacks(int callbackType, long frameTimeNanos) {
        CallbackRecord callbacks;
        synchronized (mLock) {
            final long now = SystemClock.uptimeMillis();
            //找到当前能触发的回调链表
            callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(now);
            if (callbacks == null) {
                return;
            }
            mCallbacksRunning = true;
        }
        try {
            for (CallbackRecord c = callbacks; c != null; c = c.next) {
                //循环遍历,回调所有的任务
                c.run(frameTimeNanos);
            }
        } finally {
            synchronized (mLock) {
                mCallbacksRunning = false;
                do {
                    final CallbackRecord next = callbacks.next;
                    recycleCallbackLocked(callbacks);
                    callbacks = next;
                } while (callbacks != null);
            }
        }
    }
    //回收回调任务资源
    private void recycleCallbackLocked(CallbackRecord callback) {
        callback.action = null;
        callback.token = null;
        callback.next = mCallbackPool;
        mCallbackPool = callback;
    }
    private final class CallbackQueue {
        public CallbackRecord extractDueCallbacksLocked(long now) {
            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重置为原始链表截断的头部
            mHead = next;
            return callbacks;
        }
    }
}

6.2、处理Choreographer回调

2、Choreographer的使用部分讲述了ViewRootImpl使用Choreographer的使用,那么我们现在来看一下ViewRootImplChoreographer回调时间的处理。

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
    Choreographer mChoreographer;
    /***部分代码省略***/
    public ViewRootImpl(Context context, Display display) {
        /***部分代码省略***/
        mChoreographer = Choreographer.getInstance();
        /***部分代码省略***/
    }
    /***部分代码省略***/
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
        }
    }
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            //开始View的测量、布局、绘制
            doTraversal();
        }
    }
    final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
}

7、总结

整片文章单独看起来留下的印象不是很深刻,以前阅读过 Android的16ms和垂直同步以及三重缓存 这篇文章之后就会知道本文章是对 Android的16ms和垂直同步以及三重缓存 这篇文章其中的一些疑问进行解答。从代码的角度讲述了android的屏幕绘制部分知识。

文章到这里就全部讲述完啦,若有其他需要交流的可以留言哦~!~!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容