随着产品的更新上线,迎来了短暂的休闲期,借此来总结一下最近完成的任务–有关Android过度绘制的优化。
过度绘制概念:
在屏幕一个像素上绘制多次(超过一次)。比如一个TextView后有背景,那么显示文本的像素至少绘了两次,一次是背景,一次是文本。
一个形象的解释:如果粉刷过一间房间,就会知道给墙壁涂上颜色需要做大量的工作。假如你还要重新粉刷一次的话,第二次粉刷的颜色会覆盖住第一次的颜色,第一次的颜色就永远不可见了,等于你第一次粉刷做的大量工作就完全被浪费掉。
颜色标识: GPU过渡绘制从好到差:蓝-绿-淡红-红
蓝色1x过度绘制
绿色2x过度绘制
淡红色3x过度绘制
红色超过4x过度绘制
产生的原因
冗余的背景
嵌套的layout
解决方法
一、利用Hierarchy Viewer(一个能够以可视化的角度直观的获得UI布局设计的结构和各种属性信息的工具),对某一个UI的布局进行分析,得到整体的布局图,通过观察相关的属性查看是否有冗余的layout。
二、一般在Activity中,如果使用到了
setContentView(R.layout.XXX);
一般都会存在至少两层的绘制,一层是窗口window的绘制,一层是布局的背景(如果存在背景的话)。如果是这种情况,可以将这个window背景去掉,这个背景的重绘是系统级别的,和主题有关。
解决:
Tthis.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
去除窗口的绘制即可。
教训:
1.在不同安卓版本的测试机中,去掉相同层次的背景色后,有的显示正常,有的则出现了一个非常严重的问题:背景会出现透明。
2.顶部状态栏出现了白边问题
分析原因:
1.在优化过程中,优化的过渡,没有考虑到在布局的底层留一层背景色,导致在有的机型上,会出现透明的背景。
2.在使用@drawable/transparent 作为透明背景时,就会出现白边问题,应该是使用透明图片做背景时,在绘制时会突出边缘部分,导致白边问题。
其他解决方案:
- 背景layout中已经有了颜色,如果存在对应的activity,则在activity中采用this.getWindow()的方法将窗口设为透明色,而layout的背景色不做处理;
- 如果有一个layout中嵌套多个其他view,则保持当前layout的背景色不变,将嵌套的其他view的背景色全部改成透明色(如果view的背景色和被包含的layout的背景色一致);
- 为了避免出现黑色背景,可以将背景设置为:
既保证该层不会绘制,也同时保证不会出现黑色背景(一般该情况是针对有PullToRefreshListView布局的)当然也可以在代码中,将其背景色设置为透明。android:background="@drawable/transparent"
布局设计建议:
- 布局设计在牵涉到嵌套时,应该注意嵌套的布局的背景色是否和被嵌套的布局背景色一致,如果一致可以考虑去除相同的背景色,减少绘制;
- 在布局中,如果存在多个线性布局重叠时,可以考虑只针对最上层的布局设置背景色,而不需要每一个布局(例如LinearLayout)都设置背景色,过多的相同的背景色会导致过度绘制;
- 在设计到activity类中,如果牵涉到的布局存在背景色,可以考虑消除窗口的背景色,减少1X的绘制。
总结:
- 针对过度绘制的优化,其实还有很多的方法,主要包括针对UI布局的优化(ViewStub的使用、include、merge等标签的使用)、自定义布局中绘制背景时的考量等,在优化过程中,一方面要尽可能的减少绘制,另一方面,还不能破坏总体的视觉效果,需要做综合的考虑。
- 利用工具Hierarchy Viewer可以快速帮助自己熟悉项目的布局设计情况,间接的帮助自己熟悉项目代码,非常不错。
- 在Android的过度绘制优化上,自己做的工作还是很皮毛的。Android性能优化,自己也是刚刚一脚踏入这块“神圣之地”。