性能优化系列阅读
- Android性能优化
- 性能优化 - 消除卡顿
- 性能优化 - 内存优化
- 性能分析工具 - TraceView
- Android性能分析工具
消除卡顿
- 什么是卡顿及卡顿的衡量标准
- 产生卡顿的原因
- 通用优化流程
- 定位卡顿原因
什么是卡顿
卡顿是人的一种视觉感受,比如我们滑动界面时,如果滑动不流程我们就会有卡顿的感觉,这种感觉我们需要有一个量化指标,在编程时如果开发的程序超过了这个指标我们认为其是卡顿的。
FPS(帧率):每秒显示帧数(Frames per Second)。表示图形处理器每秒钟能够更新的次数。高的帧率可以得到更流畅、更逼真的动画。一般来说12fps大概类似手动快速翻动书籍的帧率,这明显是可以感知到不够顺滑的。30fps就是可以接受的,但是无法顺畅表现绚丽的画面内容。提升至60fps则可以明显提升交互感和逼真感,但是一般来说超过75fps就不容易察觉到有明显的流畅度提升了,如果是VR设备需要高于75fps,才可能消除眩晕的感觉。
开发app的性能目标就是保持60fps,这意味着每一帧你只有16ms≈1000/60的时间来处理所有的任务。Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps。
如果你的某个操作花费时间是24ms,系统在得到VSYNC信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面。
如果此时用户在看动画的执行或者滚动屏幕(如RecyclerView),就会感觉到界面不流畅了(卡了一下)。丢帧导致卡顿产生。
流畅的情况下:
出现了丢帧现象(卡顿)
严重丢帧(卡死了)
给我们一种感觉,如果帧率越低,卡顿就越严重,那么是不是就可以使用帧率来衡量卡顿那?
如何衡量卡顿
FPS的高低不能准确的反映应用的流程度。如下图所示,只有有更新的时候才刷新界面。
当界面没有变动的时候,手机不需要对界面进行更新,所以此时的FPS会很低,如果1秒钟内都没有变动那么FPS=0。所以我们需要利用其他方式来衡量应用的流程度,比如可以利用丢帧数来衡量。
单位时间内丢帧数可以反映出应用是否流程。不丢帧是终极目标,但每秒丢帧在6-7帧左右可以接受,如果丢10帧以上就需要优化了。
丢帧情况(单位时间内均匀分布) | 卡顿情况 |
---|---|
0-10帧 | 流畅 |
10-20帧 | 较卡 |
20-40帧 | 很卡 |
40-60帧 | 卡死了 |
对于我们开发人员来说,会使用一些工具找出卡顿比较集中的地方,找出原因,消除或减弱卡顿。(测试团队会有专门的工具去测试丢帧的情况)
卡顿产生的原因
核心:分析在16ms中我们的应用做了什么工作,那些工作阻止我们在16ms时更新界面。
通常情况下,在16ms中我们有那些工作需要处理。
单以XML布局被绘制出来为例进行说明。
处理过程:
- CPU负责把UI组件计算成多边形和纹理
- OpenGL负责绘制图像(Display List)
- GPU栅格化需要显示内容并渲染到屏幕上
而实际开发中我们还加入交互、业务处理等工作,这些工作都需要在16ms中处理完成。对于开发人员来说,需要有一个工具,很直观的帮助我们判断出那些工作占用了多少时间。
Profile GPU Rendering
通过手机开发者选项中提供的Profile GPU Rendering(GPU呈现模式分析)功能,我们可以清楚的看到处理流程中各部分的耗时。手机端工具(开发助手àGPU渲染图)。建议大家在Android6.0及以上手机测试。
打开Profile GPU Rendering操作截图如下:
大家可以拿着真机配置一下。看看有什么变化。
条形图说明
- 水平方向的一根绿线代表16ms。
- 每条都代表一帧画面所有工作内容
- 每条中不同的颜色代表不同的工作内容
Android6.0及以上的手机颜色对应关系如下:
原因分析
通用优化流程
第一步:UI层优化
1、UI问题比较容易查找
2、一旦出现问题影响范围广(xml、mesure、layout、draw、Display List 、栅格化……)
工具:设备过渡绘制查看功能、HierarchyViewer等
常见问题:过渡绘制、布局复杂、层级过深……
过渡绘制
在屏幕一个像素上绘制多次(超过两次)。如:文本框,如果设置了背景颜色(黑色),那么显示的文字(白色)就需要在背景之上再次绘制。
打开手机开发者中的过渡绘制区域即可查看。蓝色标识这个区域绘制了两次。
说明:
- 如果大面积都是蓝色,属于正常情况。
- 重点关注大面积绿色及以后的,表示存在过渡绘制。
设备中的该选项只能直观的让我们感受到应用的界面是否存在过渡绘制,如果存在,我们需要利用Hierarchy Viewer查找布局中不合理的地方。
过渡绘制小案例
效果图如下
大面积存在过渡绘制,文字区域最严重。查询Item布局文件找出过渡绘制的原因
自定义控件绘制优化
Clip Rect 与 Quick Reject
- Clip Rect:识别可见区域
- Quick Reject:控件所在的矩形区域是否有交集
在Canvas中有上述两个方法,帮助我们进行判断,避免出现过渡绘制。
我们可以通过canvas.clipRect()来帮助系统识别那些可见的区域,在这个区域之外的我们不在进行绘制。如侧拉菜单,当菜单显示的时候被菜单遮挡的部分是不用进行绘制的,一旦绘制就会出现过渡绘制现象。系统的控件会控制过渡绘制,但我们自己的控件就需要自行管理了。所以在使用侧拉菜单时就需要优先考虑系统提供的了。
如果系统没有提供的,我们自己编写时也需要注意,避免出现过渡绘制。
自定义控件过渡绘制
案例效果
编写自定义控件MyVIew,在布局中引入该控件
<com.itheima.overdrawdemo.MyView
android:layout_width="match_parent"
android:layout_height=