Android性能优化(1) ——布局优化

来源:互联网 发布:aso关键字优化技巧 编辑:程序博客网 时间:2024/05/18 04:49

本篇是关于布局优化部分。主要介绍使用抽象布局标签(本文介绍 include,viewstub,merge)以及如何使用相关工具(hierarchy viewer ,lint)来辅助优化。

1.抽象布局标签

(1). <include>标签

include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模板化,这在布局里面编写方便提供了大大的便利。

下面以一个布局main.xml中用include引入另一个布局foot.xml为例。

main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <ListView        android:id="@+id/simple_list_view"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_marginBottom="@dimen/dp_80" />    <include layout="@layout/foot.xml" /></RelativeLayout>



其中include引入的foot.xml为公用的页面底部,代码如下:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" ><Button        android:id="@+id/button"        android:layout_width="match_parent"        android:layout_height="@dimen/dp_40"        android:layout_above=“@+id/text"/>    <TextView        android:id="@+id/text"        android:layout_width="match_parent"        android:layout_height="@dimen/dp_40"        android:layout_alignParentBottom="true"        android:text="@string/app_name" /></RelativeLayout>


<include>标签唯一需要的属性只有layout,即指定需要包含的布局文件。

(2). <viewstub>标签

viewstub标签通include标签一样可以用来引入一个外部布局,不同的是,viewstub引入的布局默认不会被加载,既不会占用显示空间,从而在解析layout时节省内存。

viewstub常用来引入那些默认不显示,只在特殊情况下显示的布局,比如进度布局、失败布局、出错布局等;

下面以在一个布局main.xml中加入网络错误时提示页面network_error.xml的布局为例。

main.xml文件:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" >    ……    <ViewStub        android:id="@+id/network_error_layout"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout="@layout/network_error" /></RelativeLayout>



其中network_error.xml为只有在网络加载错误是才需要显示的布局,默认是不会加载和显示的。

network_error.xml文件:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <Button        android:id="@+id/network_setting"        android:layout_width="@dimen/dp_160"        android:layout_height="wrap_content"        android:layout_centerHorizontal="true"        android:text="@string/network_setting" />    <Button        android:id="@+id/network_refresh"        android:layout_width="@dimen/dp_160"        android:layout_height="wrap_content"        android:layout_below="@+id/network_setting"        android:layout_centerHorizontal="true"        android:layout_marginTop="@dimen/dp_10"        android:text="@string/network_refresh" /></RelativeLayout>


在java中通过findViewById找到viewstub,使用viewstub.inflate()加载ViewStub,然后得到子View:


private View networkErrorView;private void showNetError() {    // not repeated infalte    if (networkErrorView != null) {        networkErrorView.setVisibility(View.VISIBLE);        return;    }    ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);    networkErrorView = stub.inflate();    Button networkSetting = (Button)networkErrorView.findViewById(R.id.network_setting);    Button refresh = (Button)findViewById(R.id.network_refresh);}private void showNormal() {    if (networkErrorView != null) {        networkErrorView.setVisibility(View.GONE);    }}


这里showNetError()中加载了ViewStub,同时,定义了一个全局的networkErrorView,用于保存该view,避免再次需要inflate,这也是优化的一部分。

p.s. 联想到view有GONE,VISIBLE,INVISIBLE,可以想到,当把某个view标签设定为GONE时,在初始化时候是不会被解析加载到内存的,这样有利于解析的效率,而另外两个都会正常加载。

(3). <merge>标签

在使用include标签后可能会导致布局嵌套过多,多出一些不必要的中间节点,从而导致解析变慢。具体嵌套的细节可以通过hierarchyviewer来查看。

merge标签的使用场景有两个:

a. 自用:即自用的布局文件(而不是给别的layout去include的), 当该布局文件顶节点是FrameLayout并且不需要设置background或者padding等属性,可以用merge作为顶结点标签。因为Activity的内容试图顶级视图就是个FrameLayout,所以通过使用merge标签,可以去除这个FrameLayout, 将该merge标签下的所有子布局直接加载到布局文件中;

b. 它用:当被include用于其他布局文件时,使用merge作为顶结点,这样在被引入时顶结点会自动被忽略,而将所有的子节点或者子布局全部合并到主布局中。

对于(1)中的布局文件,使用hierarchy viewer查看 main.xml布局如下:

c

可以发现,使用include时,会将footer.xml一股脑儿都拷贝过来,当然包括其顶结点RelativeLayout,但事实上这层RelativeLayout是没有必要存在的,所以此时只要将footer.xml的顶结点修改为merge标签,此时就会把footer.xml中merge标签下的所有子布局或者控件都直接加载过来,忽略merge这层顶结点。再次运行hierarchy viewer可以看到:

f

2. 使用hierarchy viewer 和 lint 工具

hierarchy viewer的使用如上图所示,是伴随Android SDK tools一起提供的,可以用来查看应用中的布局层级,针对某些部分的布局,可以减少掉一部分冗余的节点;

lint是ADT 16 以后提供的工具,它是一个代码扫描工具,可以用来查找代码结构中可能存在的问题。主要包括:

(1). 布局的性能 (可以检测一些冗余嵌套的布局问题);

(2). 未使用到的资源(比如图片或者一些xml文件等);

(3). 可用性问题(比如某些标签并没有某些属性,没有指定文本字段的输入类型等);

(4). 国际化问题(比如String的统一定义);

(5). manifest.xml文件错误。

使用示例:

lint会检测未国际化操作的问题,提示将字符统一放在String下面定义:

98a0937ftb63e412a0e7b&690

lint会检查那些已经添加进来的资源文件或者已经定义在xml或者代码内的未被使用的控件或者变量,从而对代码结构优化瘦身:

98a0937ftb63e2e5cec21&690

当然,还包括那些在布局文件中,使用不当的标签属性,规范性,图片资源的多分辨率问题等。

0 0
原创粉丝点击