图形重绘Overdraw
在Android界面上,图形的绘制与真实的绘画是非常类似的,例如绘画中先填充背景色,再在背景色上进行绘画。例如在一个LinearLayout中绘制蓝色背景色,再在LinearLayout上半部分画满绿色的Button,这样上面一半LinearLayout的背景色就被浪费了,成为了Overdraw的图形。因为Android系统在绘制这些View的时候,其实并不知道哪些View是可见的、不被遮挡的,它只能根据设置全部绘制。然后大量重复的绘制会导致系统做很多无用功,延长了绘制的时间,降低了绘制的效率。
在Android 4.4里面,Google采用了Overdraw Avoidance技术,系统可以自带检测Overdraw,避免过多的Overdraw。但是这个功能非常有限,只有当两个View全部遮挡时,才会触发。因此,开发者在减少Overdraw的时候,大部分时间还是得靠自己。
Overdraw与布局冗余检测实例
界面重绘和布局冗余应该是UI性能优化中最容易被修改的部分,下面笔者以一个实例来讲解一下如何进行检测和分析。示例所使用的布局代码如下所示。
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context="com.xys.preferencetest.MainActivity">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <TextView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#bebebe"
- android:gravity="bottom"
- android:text="First TextView"/>
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="400dp">
- <TextView
- android:layout_width="match_parent"
- android:layout_height="400dp"
- android:background="#7c7575"
- android:gravity="bottom"
- android:text="Second TextView"/>
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="300dp">
- <TextView
- android:layout_width="match_parent"
- android:layout_height="300dp"
- android:background="#bebebe"
- android:gravity="bottom"
- android:text="Third TextView"/>
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="200dp">
- <TextView
- android:layout_width="match_parent"
- android:layout_height="200dp"
- android:background="#7c7575"
- android:gravity="bottom"
- android:text="Fourth TextView"/>
- </LinearLayout>
- </RelativeLayout>
这个布局所显示的效果如图6.4所示。
四个TextView从大到小,依次叠加摆放。按照步骤,先打开Debug GPU Overdraw工具,查看重绘界面,显示如图6.5所示。
图6.4 重叠布局
图6.5 检测重叠布局
由于这四个TextView是叠加摆放的,所以上面的TextView发生了重绘问题。通过这个工具可以很快地找到具体的重绘点,通常情况下可以通过下面所列举的方法进行修改。
- 控件重叠摆放:改善布局方式,避免重叠。
- 控件与主背景颜色相同:可移除控件背景(移除不必要的背景)。
- 自定义View重叠:在绘制时,使用clipRect属性减少重绘区域。
接下来,再使用Hierarchy Viewer工具查看布局,显示如图6.6所示。
图6.6 Hierarchy Viewer
在ContentView这样一个根布局中,出现了四个线型的View树,也就是上面的四个无效的线型布局。通过这个工具可以快速找到冗余的布局,从而去掉冗余布局来提高性能。同时还需要尽可能降低UI的层级,将UI树扁平化,提高绘制的效率,而页面计算、布局、绘制的时间都可以在图中找出来。
