UI 优化
研究表明,0-100毫秒以内的延迟对人来说是瞬时的,100-300毫秒则会感觉明显卡顿,300-1000毫秒会让用户觉得“手机卡死了”,超过1000ms就会让用户想去干别等事情了。
早期android用户抱怨最多的就是UI,尤其是触碰反馈和动画流畅度,感觉都很卡。后来随着android系统逐渐成熟,开发人员也投入了大量的时间和精力让交互变的流畅起来。下面列举一些不同系统版本所带来的提升:
在Gingerbread或者更早的设备上,屏幕完全是由软件绘制(CPU绘制)的(不需要GPU的参与)。后来随着屏幕尺寸变大和像素的提升,纯粹靠软件绘制遇到了瓶颈。
Honeycomb加入了平板设备,进一步增加了屏幕尺寸。同时出于性能考虑,加入了GPU芯片,app在渲染内容的时候多了一个GPU硬件加速的选项。
对于针对Ice Cream Sandwich或者更高系统的设备,GPU硬件加速是默认打开的。将软件绘制(CPU)的压力大部分转移到了GPU上。
Jelly Bean 4.1 (and 4.2) “Project Butter” 做了近一步的提升来避免卡顿,通过引入VSYNC机制和增加额外的frame buffer,运行 Jelly Bean的设备丢帧的概率变的更小。引入这些机制的同时,android开发团队还加入了一些优秀的工具来测量屏幕的绘制。
1. 渲染优化
应用的卡顿问题主要原因是因为渲染性能,如果应用的动画效果,图片过多,Android系统有可能无法及时完成复杂的界面渲染操作。Android系统每隔16ms发出VSYNC(垂直同步)信号,出发对UI的渲染。如果每次都渲染成功,这样就能达到流畅的画面所需要的60fps,为了完成这个目标,意味着大多数操作都必须再16ms内完成。
如果在16ms内没有完成操作,则会出现丢帧的现象,用户在32ms内看到的是同一针画面。就是卡顿的现象。
为什么是60fps?
Tips: 这是因为人眼与大脑之间的协作无法感知超过60fps的画面更新。12fps大概类似手动快速翻动书籍的帧率,这明显是可以感知到不够顺滑的。24fps使得人眼感知的是连续线性的运动,这其实是归功于运动模糊的效果。24fps是电影胶圈通常使用的帧率,因为这个帧率已经足够支撑大部分电影画面需要表达的内容,同时能够最大的减少费用支出。但是低于30fps是无法顺畅表现绚丽的画面内容的,此时就需要用到60fps来达到想要的效果,当然超过60fps是没有必要的(据说Dart能够带来120fps的体验)。
会有很多原因导致无法渲染,比如ListView的复杂操作,过多的层叠布局,复杂的layout等,过多的动画执行次数。
2. 过度绘制(OverDraw)
过度绘制是指的在屏幕上某个像素的同一帧被绘制了多次,在多层次的UI结构中,如果不可见的UI也在被绘制,会浪费大量的资源。
Android系统设置,开发者选项,调试GPU过度绘制打开之后可以查看页面过度绘制的情况
深红色区域表示有4倍过度绘制,浅红色表示有3倍,绿色和蓝色表示绘制状况良好,应当尽量减少红色和浅红色区域的屏幕上的占比。
应用汇OverDraw情况:
- 首页五个tab:
游戏,软件,值得玩tab中每个fragment基本都是大面积的红色区域。
- 话题
- 详情页
过于复杂的布局,嵌套多层的结构就会造成过度绘制。对于过于复杂的布局以及部分不可见布局的加载可以使用(include、merge、viewStub)标签处理。
在KitKat或者更新的设备里,overdraw被大幅度的削减了。这项技术叫overdraw avoidance,系统可以检测发现简单的overdraw场景(比如一个view完全盖住了另一个view),然后自动移除额外的绘制 。(只是简单的覆盖情况)
可以使用clipRect定义视图绘制的边缘。使用clipRect之后将会只绘制设定的区域,而不会进行额外的绘制。比如侧滑菜单。
使用hierarchyViewer检查view层次结构: hierarchyViewer是一个检查view层次结构的工具,具体可以查看App的视图层次和每个view的measure,layout,draw的时间。
首页的总体层次结构:
详情页的层次结构: