视图优化
一、帧率(FPS)和刷新率
◆
帧率是GPU一秒内绘制的帧数(Frames per Second,简称:FPS)。由于人类眼睛的特殊生理结构,如果看到的画面的帧率高于24的时候,就会认为是连贯的,此现象称为视觉暂留。
当帧率达到60FPS时,显示效果就很好了,为了达到这个效果,我们就需要每16ms绘制一次视图。也就是当每次绘制的时间超过16ms,就会产生卡顿现象。这就要求我们在绘制视图时,尽量减少不必要的绘制来保证绘制效率。这就需要我们在开发过程中,对代码进行优化,减少不必要的绘制。
◆
刷新率就是硬件刷新频率。
◆ 只有帧率和刷新率完美的配合,才能使视图有一个流畅的效果。
● GPU向缓存区写入每一帧的视图数据,是一行一行地写入图像数据的写入的,而硬件从缓冲区读取数据的时候是不知道此时GPU是否刷新完这一帧图片的;
● 当帧率大于屏幕刷新率,那硬件读取的图片可能只有当前图片的一部分,这样就会产生视图割裂现象(左图);为了解决这种问题,Android引入了双缓冲机制(右图),它将缓冲区分为BackBuffer(存放没有完成的帧)和Frame Buffer(存放绘制完成的帧)两块,屏幕只拉取Frame Buffer中的数据;
● 当帧率小于刷新率时,会产生卡顿现象;
二、视图优化工具
1. 追踪过度绘制
过度绘制就是指一个像素绘制超过一次。我们可以使用“追踪过度绘制”工具,查看应用中过度绘制的地方进而进行优化。进入虚拟机的设置,打开Show GPU Overdraw选项,就可以使用这个工具。
▶ 蓝色:1x过度绘制
▶ 绿色:2x过度绘制
▶ 浅红色:3x过度绘制
▶ 深红色:4x过度绘制
2. GPU Profiler
这个工具可以快速查看渲染时间,对比16ms。
这里会显示三种柱状图,其中:
▶ 蓝色:测量绘制时间——创建更新Display List的时间;
▶ 红色:执行时间——调用OpenGL ES api,数据发送给GPU;
▶ 橙色:处理时间——CPU调用GPU绘制;
我们要保证这三种柱状图都不超过16ms的那条水平线,才能达到一个流畅的视图。
三、视图优化
1. 避免UI卡顿
☛ 避免在onDraw中创建对象——因为onDraw会被很频繁的调用,如果在onDraw中创建对象,就会导致短时间内创建大量对象引起内存抖动,UI渲染时间变长导致卡顿。我们可以使用对象池的方法优化;
☛ 减少View层级;
☛ 避免在UI顶层使用RelativeLayout——因为在它measure的时候会measure两次才能够完成对所有子View的测量,这就意味着所有的子元素都会被measure两次,这样花费的时间会更长。
☛ 尽量少使用自定义控件;
2. 优化过度绘制
☛ 降低View层级——RelativeLayout代替LinearLayout 、使用merge标签
☛ 不必要的背景——去掉window默认的背景:getWindow().setBackgroundDrawable(null);可能存在的问题是,如果控件没有充满整个屏幕,屏幕边缘没有被填充的地方,会 露出来手机桌面的背景;
去掉不必要的背景:如果父容器有设置背景,控件再设置背景,那就会造成多次绘制,在某个背景可以不需要的情况下,可以删掉这个背景的设置代码;
☛ ClipRect 和 QuickReject
☛ ViewStub
☛ .9图用作背景——.9图中全透明的像素在绘制时会优化掉,不参与绘制过程