布局优化 & 过度绘制检测
1、选择合适布局
一开始就选择一个合适的根布局,是明智的选择。合理的构思有利于减少布局层级。推荐如下优先选择:
FrameLayout > LinearLayout > RelativeLayout
·减少布局层级,层级越深,测量绘制越复杂耗时。布局应当宽而浅,而不是窄而深。
·能用一层RelativeLayout布局最好
·不要嵌套使用RelativeLayout布局,因为RelativeLayout会调用childrenView 的onMeasure()两次
·不要在嵌套的LinearLayout中都使用weight属性
··· ···
2、include重用布局
往往很多地方用到同样的布局,就可以抽取出相同的布局,作为一个单独的layout,在需要用到这种布局的地方使用<include />标签引入公共的layout,可以减少重复的代码量,同一维护修改公共布局。
定义一个公共布局public_layout.xml:
c<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>其它地方引入该公共布局:
<include layout="@layout/public_layout" />3、merge标签
使用<include />有一个问题,会增加当前布局的层级。那么就可以在定义公共layout布局的时候,使用<merge />根标签。当使用<include />加载的时候,加载布局会自动“融入”当前布局,不会产生新的层级。提高布局加载性能。
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>4、ViewStub懒加载
一些View往往一开始不需要,只在出现某些情况的下进行显示。如果单纯的用setVisibility()进行是否显示地控制,浪费了性能。因为无论View的Visibility是GONE还是INVISIBILITY还是VISIBLE,都会进行View的加载和绘制。
ViewStub就是用来解决这个问题的,按需加载,也叫懒加载,只有当需要显示该部分布局的时候才进行加载,渲染显示。ViewStub的详细用法参考另一篇博客《Android中ViewStub控件懒加载布局用法》
<ViewStub
android:id="@+id/viewstub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout="@layout/public_layout" />坑点:
①ViewStub不能为空,否则奔溃。必须为ViewGroup类型,不能为<merge />,ImageView等

ViewStub must have a non-null ViewGroup viewParent
这句话已经明说了,ViewStub只能包含为非空的,ViewGrop 父布局!
②ViewStub只能inflate()一次,多次调用会奔溃。最好直接使用setVisibility()控制显示。如果一开始没有加载,调用setVisibility会自动inflate显示ViewStub布局。
③ViewStub只要加载一次之后,Visibility一直是View.VISIBLE,就不能再通过ViewStub进行判断,而是对所加载的布局进行判断。
④ViewStub加载之后,可以直接在当前布局中通过findViewById()初始化所加载布局的子控件。
5、减少背景绘制
去掉当前Activity的Window的默认背景,设置为null,减少一层绘制。
@Override
protected void onCreate(Bundle savedInstanceState) {
... ...
Window window = getWindow();
window.setBackgroundDrawable(null);
}减少当前布局Layout 的不必要的background背景色,见View的setWillNotDraw()方法作用一文。
6、慎用alpha
透明度是通过绘制不同层级混合出的效果。.png的图片透明度绘制也会导致overdraw。
7、点9图
Android的2D渲染器会优化draw9patch中的透明区域,从而优化了overdraw。
过度绘制检测
1、检测GPU过渡绘制:Graphic Processing Unit
Android为我们提供了检测工具,布局是否存在过度绘制。
设置 > 选择开发选项(Developer Options) > 调试GPU 过度绘制(Debug GPU Overdraw)

Android 将按如下方式为界面元素着色,以确定过度绘制的次数:
- 真彩色:没有过度绘制
蓝色:过度绘制 1 次
绿色:过度绘制 2 次
粉色:过度绘制 3 次
红色:过度绘制 4 次或更多次
2、Hierarchy Viewer分析布局
Hierarchy Viewer 是 Android Device Monitor 中内置的一种工具,可让您测量布局层次结构中每个视图的布局速度。它可以帮助您查找由视图层次结构导致的性能瓶颈。目前已停止维护,推荐使用后面AndroidStudio自带的Layout Inspector。
工具在Android SDK 目录:.\sdk\tools\monitor.bat
打开如果有如下错误,是因为没有设置环境变量 ANDROID_HVPROTO=ddm

打开之后,选择需要调试分析的页面布局:

层级结构一目了然:

3、Layout Inspector 调试布局
使用 Android Studio 中的 Layout Inspector,可以将应用布局与设计模型进行比较、显示应用的放大视图,并在运行时检查其布局的细节。如果布局是在运行时(而不是完全在 XML 中)构建的并且布局表现出意外行为,这会很有用。Layout Inspector 中的大部分功能以前是由 Hierarchy Viewer 和 Pixel Perfect 工具提供的,但这些工具现已弃用。

Layout Inspector 将显示以下内容:
- View Tree:布局中视图的层次结构。
- Layout Inspector 工具栏:Layout Inspector 的工具。
- 屏幕截图:设备上显示的应用布局的屏幕截图,其中显示了每个视图的布局边界。
- Properties Table:选定视图的布局属性。


