Android中绘制的原理
Android使用的绘制引擎是Skia,而App中的动画、2D绘制、SVG矢量图都是通过该绘制引擎进行绘制,并且通过显卡输出到渲染的Buffer中,用户才能看到绘制的图形。
而在Android中,一个View绘制的过程如下:
- 通过Canvas对象将图形绘制到DisplayList中
- CPU处理DisplayList中的多维图形,处理纹理
- 通过OpenGL ES接口调用GPU,将图形纹理传入
- GPU对图形进行栅格化,然后在屏幕上显示
- 通过硬件时钟进行调用,通过
epoll
将V_SYNC
信号回调给应用进行绘制,而该信号一般都是1s绘制60帧,也就是16.6ms左右回调一次
所以,我们应该在两个V_SYNC
信号间处理事件不超过16ms。也就是我们需要保证:
- 每一帧绘制的时间不能超过16.6ms
- 主线程的MessageQueue中的Message不能够拥堵,否则会导致下个绘制的Message无法在16.6ms间隔内完成绘制
- 主线程的某个Message执行时间不能过长,否则也将退后下一帧的绘制
正常与异常情况
正常情况:
每隔16ms开始绘制下一帧
异常情况:
当一帧绘制开始的时间间隔超过16ms的话,那么VSYNC机制就会让GPU等待下一个Buffer到来再完成栅格化、渲染等操作,就会导致掉帧,用户看起来就会卡顿
通常优化的方案
- 检查过度绘制(OverDraw)
- 检查View树的层级(Hierarchy Viewer)
- 打开开发者选项中的GPU呈现模式,看看GPU的柱状图是否在绿线以下
Profiler中的CPU
在Profiler中Record一段时间后,Android Profiler会开始打印出来这段时间内的所有线程以及线程内栈帧的调用时间等。
Profiler-CPU在上面的截图中,可以看到:
doFrame
函数一共执行了8.57ms,在执行完该函数后,MessageQueue继续陷入epoll中等待下一个事件来到。
而后又接收到了一个doFrame
的事件,要求绘制。
而如果某个doFrame
中时间超过16.6ms,或者两个doFrame
之间的间隔超过16.6ms,则会导致丢帧,所以我们需要优化的也就是这些代码。
网友评论