Android屏幕刷新机制

“应用层负责绘制,系统层负责渲染,屏幕刷新机制把数据更新到屏幕上。”

看懂这张图

大家肯定都见过这张图。大家也肯定都听过这句话。

对应上图,应用层使用CPU“绘制”,系统层使用GPU“渲染”,屏幕刷新机制对应Display。

最后就是Vsync的机制,使得绘制、渲染对BackBuffer的写入和屏幕刷新机制对FrameBuffer的读取得以同步。也就是说对两个Buffer的读、写 保持同一步调

最完美的状态就是下一个刷新周期到来时,对BackBuffer的写入操作已经完成。即对应上图 “蓝+绿”<=“黄”

Triple Buffer

解释上图,双缓冲就够了。但是实现就是那么不完美。如果**“蓝+绿”>“黄”**呢?第二个刷新周期来了,bufferB还没准备好,屏幕只能继续显示bufferA,这样CPU就闲置了。

为解决这个问题,所以就有了bufferC,在bufferB还没准备好的时候往bufferC里绘制view的内容(如下图)。这样我们就有一个FrameBuffer、两个BackBuffer,合计三个buffer,即所谓的Triple Buffer

Quadruple Buffer(四倍的Buffer )

别怕!这个小标题是唬人的。如果真的有**“蓝+绿”>2“黄”**的情况发生,只能证明咱的程序太烂,要优化代码了!

必须知道的Choreographer

Android在4.1版本引入了一个重大的改进—Project Butter,也即是黄油计划。其对Android Display系统进行了重构,引入了三个核心元素,即Vsync、Triple Buffer和Choreographer。下在来看Choreographer

  • Choreographer的作用:

    对于应用层显示系统来讲,Choreographer的主要作用是协调绘制的时间(即上文说的 “保持同一步调”),它从显示子系统接收Vsync信号,然后安排绘制下一帧的数据。

  • Choreographer的实现原理:

    一句话简述:用一个队列暂存绘制任务,等Vsync信号来了,再从队列里取出任务进行绘制。

  1. 先排队绘制任务:

    ViewRootImpl#scheduleTraversals()

    —>Choreographer#postCallbackDelayedInternal()
    //绘制任务入队 //mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);

    —>—>Choreographer##scheduleFrameLocked()

    —>—>—>Choreographer##scheduleVsyncLocked()
    //这里会调用DisplayEventReceiver#scheduleVsync()

  2. 注册Vsync信号。

    DisplayEventReceiver#scheduleVsync()
    //会调到一个native方法,咱就不管它怎么实现的了

  3. 收到Vsync信号。

    DisplayEventReceiver#dispatchVsync()

    —>FrameDisplayEventReceiver#onVsync()

    —>—>Choreographer#doFrame()
    //取出绘制任务,执行绘制//doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //这个Handler的作用:延时、切换线程
    private final class FrameHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
    switch (msg.what) {
    //2开始绘图
    case MSG_DO_FRAME:
    doFrame(System.nanoTime(), 0);
    break;
    //1注册vsync信号的通知
    case MSG_DO_SCHEDULE_VSYNC:
    doScheduleVsync();
    break;
    //0安排一下,等会儿我要绘图
    case MSG_DO_SCHEDULE_CALLBACK:
    doScheduleCallback(msg.arg1);
    break;
    }
    }
    }

Choreographer扩展知识

CallbackRecord.action可以是Runnable也可以是FrameCallback, 所以我们就可以用FrameCallback来做 卡顿监测,详见:广研Android卡顿监控系统的方式4