Android APP UI卡顿的原理

一、卡顿(Jank)的定义

Android团队把滞缓,不流畅的动画定义为卡顿(jank),一般是由于丢帧引起的。从Android诞生的第一天直到现在的8核CPU,Android始终未能摆脱卡顿的问题。在Android APP的性能测试中卡顿测试是非常重要的一部分。

二、Android的"16ms"原则

Android系统每隔16ms会发出VSYNC信号重绘我们的界面(Activity)。为什么是16ms,因为Android设定的刷新率是60FPS(Frame Per Second),也就是每秒60帧的刷新率, 约16ms刷新一次。这就意味着,,我们需要在16ms内完成下一次要刷新的界面的相关运算,,以便界面刷新更新。举个例子,当运算需要24ms完成时,16ms时就无法正常刷新了,而需要等到32ms时刷新,这就是丢帧了。丢帧越多,给用户的感觉就越卡顿。

Android APP UI卡顿的原理


Android APP UI卡顿的原理
 
 三、卡顿的原因分析

我们知道,对于APP的每一个View,Android系统都会通过三个步骤来渲染:Measure(测量)、Layout(布局)和Draw(绘制)。measure从最顶部的节点开始,顺着layout树形结构依次往下测量每个view需要在屏幕中展示的尺寸大小。每个子节点都需要向父节点提供自己的尺寸来决定展示的位置,遇到冲突时,父节点可以强制子节点重新measure(可能导致时间消耗为原来的2-3倍)。因此扁平化的view结构会性能更好。

RelativeLayouts经常需要measure所有子节点两次才能把子节点合理的布局。如果子节点设置了weights属性,LinearLayouts也需要measure这些节点两次,才能获得精确的展示尺寸。如果LinearLayouts或者RelativeLayouts被套嵌使用,measure所费时间可能会呈指数级增长。

一旦view开始被measure,该view所有的子view都会被重新layout,再把该view传递给它的父view,如此重复一直到最顶部的根view。layout完成之后,所有的view都被渲染到屏幕上。需要特别注意到是,并不是只有用户看得见的view才会被渲染,所有的view都会。APP拥有的views越多,measure,layout,draw所花费的时间就越久。要缩短这个时间,关键是保持view的树形结构尽量扁平,而且要移除所有不需要渲染的view。移除这些view会对加速屏幕渲染产生明显的效果。理想情况下,总共的measure,layout,draw时间应该被很好的控制在16ms以内,以保证滑动屏幕时UI的流畅。

对于布局的检查,我们可以通过Hierarchy Viewer来检查。Hierarchy Viewer不仅可以很方便可视化的查看屏幕上套嵌的view结构,还可以点击任何一个view来展示子view的数量,和measure, layout, draw的耗时。Hierarchy Viewer还可以帮助发现overdraw(重复的绘制)。

Overdraw用来描述一个像素在屏幕上多少次被重绘在一帧上。通俗的说:理想情况下,每屏每帧上,每个像素点应该只被绘制一次,如果有多次绘制,就是overdraw。多次的重新绘制屏幕会使得绘制延迟变大,最终导致卡顿。overdraw还带来另一个问题,当view内容有更新的时候,之前绘制的view就失效了,view的每一个像素都需要重绘。Android设备没法判断哪个view是可见的,所以只能绘制每个view的相关像素。如果APP有很多层,每一层的相关像素都需要绘制一遍,一不小心,就会带来性能问题。

Android提供了一些很好的工具来检测overdraw。Jelly Bean 4.2里,开发者选项菜单里增加了Debug GPU Overdraw的选项。选择“Show Overdraw areas”选项之后,会在app的不同区域覆盖不同的颜色来表示overdraw的次数。比较屏幕上这些不同的颜色,可以快速方便的定位overdraw问题:

原色: 没有overdraw

蓝色: 1次overdraw

绿色: 2次overdraw

粉色: 3次overdraw

红色: 4次及4次以上的overdraw

在KitKat或者更新的设备里,overdraw被大幅度的削减了。这项技术叫overdraw avoidance,系统可以检测发现简单的overdraw场景(比如一个view完全盖住了另一个view),然后自动移除额外的绘制。这很明显会极大的提高设备的绘制性能。但开发者还是要尽可能的避免额外的overdraw(为了更好的性能,也为了能兼容Jelly Bean及更老的设备)。Jelly Bean 4.3 或者 KitKat 设备,在屏幕的左下角会有一个计数展示屏幕overdraw的程度。这个工具对检测overdraw十分有效。当使用这个检测工具时,KitKat的overdraw avoidance功能会被禁止。

参考链接:

http://mrpeak.cn/android/2016/01/11/android-performance-ui