Android性能优化之布局优化

来源:互联网 发布:会计培训 知乎 编辑:程序博客网 时间:2024/05/16 18:25
最新最准确内容建议直接访问原文:Android性能优化之布局优化

本文为Android性能优化的第二篇——布局优化,主要介绍使用抽象布局标签(include, viewstub, merge)、去除不必要的嵌套和View节点、减少不必要的infalte及其他Layout方面可调优点,顺带提及布局调优相关工具(hierarchy viewer和lint)
1、抽象布局标签
(1) <include>标签
include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模块化,这在布局编写方便提供了大大的便利。
下面以在一个布局main.xml中用include引入另一个布局foot.xml为例。main.mxl代码如下:
游客,如果您要查看本帖隐藏内容请回复
其中include引入的foot.xml为公用的页面底部,代码如下:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent" >

  5.     <Button
  6.         android:id="@+id/button"
  7.         android:layout_width="match_parent"
  8.         android:layout_height="@dimen/dp_40"
  9.         android:layout_above="@+id/text"/>

  10.     <TextView
  11.         android:id="@+id/text"
  12.         android:layout_width="match_parent"
  13.         android:layout_height="@dimen/dp_40"
  14.         android:layout_alignParentBottom="true"
  15.         android:text="@string/app_name" />

  16. </RelativeLayout>
复制代码
<include>标签唯一需要的属性是layout属性,指定需要包含的布局文件。可以定义android:id和android:layout_*属性来覆盖被引入布局根节点的对应属性值。注意重新定义android:id后,子布局的顶结点i就变化了。

(2) <viewstub>标签
viewstub标签同include标签一样可以用来引入一个外部布局,不同的是,viewstub引入的布局默认不会扩张,即既不会占用显示也不会占用位置,从而在解析layout时节省cpu和内存。
viewstub常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。
下面以在一个布局main.xml中加入网络错误时的提示页面network_error.xml为例。main.mxl代码如下:
游客,如果您要查看本帖隐藏内容请回复
其中network_error.xml为只有在网络错误时才需要显示的布局,默认不会被解析,示例代码如下:
游客,如果您要查看本帖隐藏内容请回复
在java中通过(ViewStub)findViewById(id)找到ViewStub,通过stub.inflate()展开ViewStub,然后得到子View,如下:
  1. private View networkErrorView;

  2. private void showNetError() {
  3.         // not repeated infalte
  4.         if (networkErrorView != null) {
  5.                 networkErrorView.setVisibility(View.VISIBLE);
  6.                 return;
  7.         }

  8.         ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
  9.         networkErrorView = stub.inflate();
  10.         Button networkSetting = (Button)networkErrorView.findViewById(R.id.network_setting);
  11.         Button refresh = (Button)findViewById(R.id.network_refresh);
  12. }

  13. private void showNormal() {
  14.         if (networkErrorView != null) {
  15.                 networkErrorView.setVisibility(View.GONE);
  16.         }
  17. }
复制代码
在上面showNetError()中展开了ViewStub,同时我们对networkErrorView进行了保存,这样下次不用继续inflate。这就是后面第三部分提到的减少不必要的infalte。
viewstub标签大部分属性同include标签类似。

上面展开ViewStub部分代码
  1. ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
  2. networkErrorView = stub.inflate();
复制代码
也可以写成下面的形式
  1. View viewStub = findViewById(R.id.network_error_layout);
  2. viewStub.setVisibility(View.VISIBLE);   // ViewStub被展开后的布局所替换
  3. networkErrorView =  findViewById(R.id.network_error_layout); // 获取展开后的布局
复制代码
效果一致,只是不用显示的转换为ViewStub。通过viewstub的原理我们可以知道将一个view设置为GONE不会被解析,从而提高layout解析速度,而VISIBLE和INVISIBLE这两个可见性属性会被正常解析。

(3) <merge>标签
在使用了include后可能导致布局嵌套过多,多余不必要的layout节点,从而导致解析变慢,不必要的节点和嵌套可通过hierarchy viewer(下面布局调优工具中有具体介绍)或设置->开发者选项->显示布局边界查看。

merge标签可用于两种典型情况:
a.  布局顶结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容试图的parent view就是个FrameLayout,所以可以用merge消除只剩一个。
b.  某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中。
以(1) <include>标签的示例为例,用hierarchy viewer查看main.xml布局如下图:

可以发现多了一层没必要的RelativeLayout,将foot.xml中RelativeLayout改为merge,如下:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <merge xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent" >

  5.     <Button
  6.         android:id="@+id/button"
  7.         android:layout_width="match_parent"
  8.         android:layout_height="@dimen/dp_40"
  9.         android:layout_above="@+id/text"/>

  10.     <TextView
  11.         android:id="@+id/text"
  12.         android:layout_width="match_parent"
  13.         android:layout_height="@dimen/dp_40"
  14.         android:layout_alignParentBottom="true"
  15.         android:text="@string/app_name" />

  16. </merge>
复制代码
运行后再次用hierarchy viewer查看main.xml布局如下图:
这样就不会有多余的RelativeLayout节点了。

2、去除不必要的嵌套和View节点
更多调优方式及调优工具介绍见原文:Android性能优化之布局优化

你可能还感兴趣:
Android性能调优
Android性能优化之数据库优化
Android 图片内存缓存
Android 图片SD卡缓存
Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
android性能优化, android性能调优, android布局优化, android_layout调优, android_include, android性能优化, android性能调优

9485060950_08b4bbfa96_o.jpg (36.21 KB, 下载次数: 0)

9485060950_08b4bbfa96_o.jpg

9485065682_fa5647b3c7_o.jpg (34.68 KB, 下载次数: 0)

9485065682_fa5647b3c7_o.jpg

9485061000_aba0991605_o.jpg (74.21 KB, 下载次数: 0)

9485061000_aba0991605_o.jpg
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享分享 分享淘帖 支持支持 反对反对

相关帖子

  • • Android性能调优工具TraceView介绍

最新最准确内容建议直接访问原文:Android性能优化之布局优化

本文为Android性能优化的第二篇——布局优化,主要介绍使用抽象布局标签(include, viewstub, merge)、去除不必要的嵌套和View节点、减少不必要的infalte及其他Layout方面可调优点,顺带提及布局调优相关工具(hierarchy viewer和lint)
1、抽象布局标签
(1) <include>标签
include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模块化,这在布局编写方便提供了大大的便利。
下面以在一个布局main.xml中用include引入另一个布局foot.xml为例。main.mxl代码如下:
游客,如果您要查看本帖隐藏内容请回复
其中include引入的foot.xml为公用的页面底部,代码如下:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent" >

  5.     <Button
  6.         android:id="@+id/button"
  7.         android:layout_width="match_parent"
  8.         android:layout_height="@dimen/dp_40"
  9.         android:layout_above="@+id/text"/>

  10.     <TextView
  11.         android:id="@+id/text"
  12.         android:layout_width="match_parent"
  13.         android:layout_height="@dimen/dp_40"
  14.         android:layout_alignParentBottom="true"
  15.         android:text="@string/app_name" />

  16. </RelativeLayout>
复制代码
<include>标签唯一需要的属性是layout属性,指定需要包含的布局文件。可以定义android:id和android:layout_*属性来覆盖被引入布局根节点的对应属性值。注意重新定义android:id后,子布局的顶结点i就变化了。

(2) <viewstub>标签
viewstub标签同include标签一样可以用来引入一个外部布局,不同的是,viewstub引入的布局默认不会扩张,即既不会占用显示也不会占用位置,从而在解析layout时节省cpu和内存。
viewstub常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。
下面以在一个布局main.xml中加入网络错误时的提示页面network_error.xml为例。main.mxl代码如下:
游客,如果您要查看本帖隐藏内容请回复
其中network_error.xml为只有在网络错误时才需要显示的布局,默认不会被解析,示例代码如下:
游客,如果您要查看本帖隐藏内容请回复
在java中通过(ViewStub)findViewById(id)找到ViewStub,通过stub.inflate()展开ViewStub,然后得到子View,如下:
  1. private View networkErrorView;

  2. private void showNetError() {
  3.         // not repeated infalte
  4.         if (networkErrorView != null) {
  5.                 networkErrorView.setVisibility(View.VISIBLE);
  6.                 return;
  7.         }

  8.         ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
  9.         networkErrorView = stub.inflate();
  10.         Button networkSetting = (Button)networkErrorView.findViewById(R.id.network_setting);
  11.         Button refresh = (Button)findViewById(R.id.network_refresh);
  12. }

  13. private void showNormal() {
  14.         if (networkErrorView != null) {
  15.                 networkErrorView.setVisibility(View.GONE);
  16.         }
  17. }
复制代码
在上面showNetError()中展开了ViewStub,同时我们对networkErrorView进行了保存,这样下次不用继续inflate。这就是后面第三部分提到的减少不必要的infalte。
viewstub标签大部分属性同include标签类似。

上面展开ViewStub部分代码
  1. ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
  2. networkErrorView = stub.inflate();
复制代码
也可以写成下面的形式
  1. View viewStub = findViewById(R.id.network_error_layout);
  2. viewStub.setVisibility(View.VISIBLE);   // ViewStub被展开后的布局所替换
  3. networkErrorView =  findViewById(R.id.network_error_layout); // 获取展开后的布局
复制代码
效果一致,只是不用显示的转换为ViewStub。通过viewstub的原理我们可以知道将一个view设置为GONE不会被解析,从而提高layout解析速度,而VISIBLE和INVISIBLE这两个可见性属性会被正常解析。

(3) <merge>标签
在使用了include后可能导致布局嵌套过多,多余不必要的layout节点,从而导致解析变慢,不必要的节点和嵌套可通过hierarchy viewer(下面布局调优工具中有具体介绍)或设置->开发者选项->显示布局边界查看。

merge标签可用于两种典型情况:
a.  布局顶结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容试图的parent view就是个FrameLayout,所以可以用merge消除只剩一个。
b.  某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中。
以(1) <include>标签的示例为例,用hierarchy viewer查看main.xml布局如下图:

可以发现多了一层没必要的RelativeLayout,将foot.xml中RelativeLayout改为merge,如下:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <merge xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent" >

  5.     <Button
  6.         android:id="@+id/button"
  7.         android:layout_width="match_parent"
  8.         android:layout_height="@dimen/dp_40"
  9.         android:layout_above="@+id/text"/>

  10.     <TextView
  11.         android:id="@+id/text"
  12.         android:layout_width="match_parent"
  13.         android:layout_height="@dimen/dp_40"
  14.         android:layout_alignParentBottom="true"
  15.         android:text="@string/app_name" />

  16. </merge>
复制代码
运行后再次用hierarchy viewer查看main.xml布局如下图:
这样就不会有多余的RelativeLayout节点了。

2、去除不必要的嵌套和View节点
更多调优方式及调优工具介绍见原文:Android性能优化之布局优化

你可能还感兴趣:
Android性能调优
Android性能优化之数据库优化
Android 图片内存缓存
Android 图片SD卡缓存
Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
android性能优化, android性能调优, android布局优化, android_layout调优, android_include, android性能优化, android性能调优

9485060950_08b4bbfa96_o.jpg (36.21 KB, 下载次数: 0)

9485060950_08b4bbfa96_o.jpg

9485065682_fa5647b3c7_o.jpg (34.68 KB, 下载次数: 0)

9485065682_fa5647b3c7_o.jpg

9485061000_aba0991605_o.jpg (74.21 KB, 下载次数: 0)

9485061000_aba0991605_o.jpg
0 0