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
信号来了,再从队列里取出任务进行绘制。
先排队绘制任务:
ViewRootImpl#scheduleTraversals()
—>Choreographer#postCallbackDelayedInternal()
//绘制任务入队 //mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
—>—>Choreographer##scheduleFrameLocked()
—>—>—>Choreographer##scheduleVsyncLocked()
//这里会调用DisplayEventReceiver#scheduleVsync()
注册
Vsync
信号。DisplayEventReceiver#scheduleVsync()
//会调到一个native方法,咱就不管它怎么实现的了收到
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 {
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