过度绘制(Overdraw)是指在一帧的时间内像素被绘制了多次;
理论上一个像素每次只绘制一次是最优的,但是由于层叠的布局导致一些像素会被多次绘制,而每次绘制都会对应到CPU的一组绘图命令和GPU的一些操作,所以对重叠不可见元素的重复绘制会产生额外的计算,需要尽量减少Overdraw的发生。
Android系统提供了测量Overdraw的选项,在开发者选项-调试GPU过度绘制(Show GPU Overdraw),打开选项就可以看到当前页面Overdraw的状态。
根据overdraw的次数会显示不同的颜色来区分
- transparent = no overdraw
- blue = 1 layer
- green = 2 layers
- light-red = 3 layers
- dark red = you’re doing it wrong
优化方法
总的原则就是:尽量避免重叠不可见元素的绘制
- 去除不需要的背景资源
- 在theme中添加
android:windowbackground="null"
; - 在Activity中设置getWindow().setBackgroundDrawable(null)
这个方法要在setContentView()之后,因为getWindow().setBackground(Drawable)会讲这里的Drawable设置到DecorView的background,默认是0xff000000,而setContentView才会第一次初始化phoneWindow的DecorView;
- 在theme中添加
- 分段设置背景
有时候为了方便会先给Layout设置一个整体的背景,再给子View设置背景,这里也会造成重叠,如果子View宽度mach_parent,可以看到完全覆盖了Layout的一部分,这里就可以通过分别设置背景来减少重绘。
- View onDraw()方法
自定义View绘制时避免重叠部分的绘制,可以使用
canvas.clipRect(); // 裁剪canvas
canvas.quickReject(); // 判断矩形区域是否相交
其他绘制优化建议
- 在onDraw函数里尽量避免分配内存、创建对象,会导致频繁的垃圾回收降低性能;
在初始化、或者动画间隙做这些事情
- 减少invalidate的调用
- 尽可能保持layout的扁平化,尽可能少调用requestLayout(),requestLayout会导致系统遍历整个View树重新去measure和layout,如果layout嵌套复杂,这里也会产生性能问题
- 如果布局复杂,可以考虑自定义ViewGroup来特殊处理
Reference
Android Performance Patterns: Understanding Overdraw
Android Performance Patterns: Invalidations, Layouts, and Performance
时间: 2024-10-10 02:23:38