码个蛋(codeegg)第 806 次推文
作者:LooperJing
博客:https://www.jianshu.com/p/9ac245657127
码妞看世界
乌桕树叶红了。
写在前面
优化性能一般从渲染,运算与内存,电量三个方面进行。
今天聊一聊Android的渲染机制,我们要知道Android系统每隔 16ms就重新绘制一次Activity,也就是说,我们的应用必须在16ms内完成屏幕刷新的全部逻辑操作,即每一帧只能停留16ms,渲染机制说完之后,然后在说如何去优化UI。
1、为什么是16ms
16ms意味着1000/60hz,相当于60fps。
这是因为人眼与大脑之间的协作无法感知超过60fps的画面更新。
12fps大概类似手动快速翻动书籍的帧率, 这明显是可以感知到不够顺滑的。
24fps使得人眼感知的是连续线性的运动,这其实是归功于运动模糊的效果。24fps是电影胶圈通常使用的帧率,因为这个帧率已经足够支撑大部分电影画面需要表达的内容,同时能够最大的减少费用支出。
但是低于30fps是无法顺畅表现绚丽的画面内容的,此时就需要用到60fps来达到想要的效果,超过60fps就没有必要了。如果我们的应用没有在16ms内完成屏幕刷新的全部逻辑操作,就会发生卡顿。
2、为什么16ms没完成绘制就会卡顿?
Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,VSync是Vertical Synchronization(垂直同步)的缩写,是一种在PC上很早就广泛使用的技术,可以简单的把它认为是一种定时中断。而在Android 4.1(JB)中已经开始引入VSync机制。
上图所示是VSync机制下的绘制过程。
从上图可以看出,CPU和GPU的处理时间都少于一个VSync的间隔,即16.6ms。如果每个间隔都有绘制的情况下,当前的FPS即为60帧。
当CPU和GPU处理时间都很慢,或因为其他的原因,如在主线程中干活太多,那么就会出现如下图这样的状况。
从上图可以看到,CPU和GPU的处理时间因为各种原因都大于一个VSync的间隔(16.6ms),所以在第二个VSync还在处理1区域的绘制时,不可能实现理论上的FPS60,同时也出现了丢帧(SF: Skipped Frame)情况。
试想用户盯着同一张图看了32ms而不是16ms,当然很容易察觉出卡顿感,哪怕仅仅出现一次掉帧,用户都会发现动画不是很顺畅,大家在察觉到APP卡顿的时候,可以看看logcat控制台,会有drop frames类似的警告,那么是什么原因导致16ms没能完成绘制的操作呢?
3、渲染原理
上面说了CPU和GPU的处理时间因为各种原因都大于一个VSync的间隔(16.6ms),导致了卡顿。
渲染操作通常依赖于两个核心组件:CPU与GPU。
CPU负责包括Measure,Layout,Record,Execute的计算操作,
GPU 负责Rasterization(栅格化)操作。
何为栅格化,我也是第一次听到这词,看下图。