主要介绍使用抽象布局标签(include, viewstub, merge)、去除不必要的嵌套和View节点、减少不必要的infalte及其他Layout方面可调优点,顺带提及布局调优相关工具(hierarchy viewer和lint)。

1、抽象布局标签

(1) <include>标签
include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模块化,这在布局编写方便提供了大大的便利。
下面以在一个布局main.xml中用include引入另一个布局foot.xml为例。main.mxl代码如下:

[java] view plaincopy
  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. <ListView
  6. android:id="@+id/simple_list_view"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. android:layout_marginBottom="@dimen/dp_80" />
  10. <include layout="@layout/foot.xml" />
  11. </RelativeLayout>

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

[java] view plaincopy
  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代码如下:

[java] view plaincopy
  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. ……
  6. <ViewStub
  7. android:id="@+id/network_error_layout"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. android:layout="@layout/network_error" />
  11. </RelativeLayout>

其中network_error.xml为只有在网络错误时才需要显示的布局,默认不会被解析,示例代码如下:

[java] view plaincopy
  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/network_setting"
  7. android:layout_width="@dimen/dp_160"
  8. android:layout_height="wrap_content"
  9. android:layout_centerHorizontal="true"
  10. android:text="@string/network_setting" />
  11. <Button
  12. android:id="@+id/network_refresh"
  13. android:layout_width="@dimen/dp_160"
  14. android:layout_height="wrap_content"
  15. android:layout_below="@+id/network_setting"
  16. android:layout_centerHorizontal="true"
  17. android:layout_marginTop="@dimen/dp_10"
  18. android:text="@string/network_refresh" />
  19. </RelativeLayout>

在java中通过(ViewStub)findViewById(id)找到ViewStub,通过stub.inflate()展开ViewStub,然后得到子View,如下:

[java] view plaincopy
  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部分代码

[java] view plaincopy
  1. ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
  2. networkErrorView = stub.inflate();
  3. 也可以写成下面的形式
  4. View viewStub = findViewById(R.id.network_error_layout);
  5. viewStub.setVisibility(View.VISIBLE);   // ViewStub被展开后的布局所替换
  6. 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,如下:

[java] view plaincopy
  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节点
(1) 首次不需要使用的节点设置为GONE或使用viewstub
(2) 使用RelativeLayout代替LinearLayout
大约在Android4.0之前,新建工程的默认main.xml中顶节点是LinearLayout,而在之后已经改为RelativeLayout,因为RelativeLayout性能更优,且可以简单实现LinearLayout嵌套才能实现的布局。
4.0及以上Android版本可通过设置->开发者选项->显示布局边界打开页面布局显示,看看是否有不必要的节点和嵌套。4.0以下版本可通过hierarchy viewer查看。
 
3、减少不必要的infalte
(1) 对于inflate的布局可以直接缓存,用全部变量代替局部变量,避免下次需再次inflate
如上面ViewStub示例中的

[java] view plaincopy
  1. if (networkErrorView != null) {
  2. networkErrorView.setVisibility(View.VISIBLE);
  3. return;
  4. }

(2) ListView提供了item缓存,adapter getView的标准写法,如下:

[java] view plaincopy
  1. @Override
  2. public View getView(int position, View convertView, ViewGroup parent) {
  3. ViewHolder holder;
  4. if (convertView == null) {
  5. convertView = inflater.inflate(R.layout.list_item, null);
  6. holder = new ViewHolder();
  7. ……
  8. convertView.setTag(holder);
  9. } else {
  10. holder = (ViewHolder)convertView.getTag();
  11. }
  12. }
  13. /**
  14. * ViewHolder
  15. *
  16. * @author trinea@trinea.cn 2013-08-01
  17. */
  18. private static class ViewHolder {
  19. ImageView appIcon;
  20. TextView  appName;
  21. TextView  appInfo;
  22. }
其他点

(1) 用SurfaceView或TextureView代替普通View
SurfaceView或TextureView可以通过将绘图操作移动到另一个单独线程上提高性能。
普通View的绘制过程都是在主线程(UI线程)中完成,如果某些绘图操作影响性能就不好优化了,这时我们可以考虑使用SurfaceView和TextureView,他们的绘图操作发生在UI线程之外的另一个线程上。
因为SurfaceView在常规视图系统之外,所以无法像常规试图一样移动、缩放或旋转一个SurfaceView。TextureView是Android4.0引入的,除了与SurfaceView一样在单独线程绘制外,还可以像常规视图一样被改变。
 
(2) 使用RenderJavascript
RenderScript是Adnroid3.0引进的用来在Android上写高性能代码的一种语言,语法给予C语言的C99标准,他的结构是独立的,所以不需要为不同的CPU或者GPU定制代码代码。
 
(3) 使用OpenGL绘图
Android支持使用OpenGL API的高性能绘图,这是Android可用的最高级的绘图机制,在游戏类对性能要求较高的应用中得到广泛使用。
Android 4.3最大的改变,就是支持OpenGL ES 3.0。相比2.0,3.0有更多的缓冲区对象、增加了新的着色语言、增加多纹理支持等等,将为Android游戏带来更出色的视觉体验。
 
(4) 尽量为所有分辨率创建资源
减少不必要的硬件缩放,这会降低UI的绘制速度,可借助Android asset studio
 
5、布局调优工具
(1) hierarchy viewer
hierarchy viewer可以方便的查看Activity的布局,各个View的属性、measure、layout、draw的时间,如果耗时较多会用红色标记,否则显示绿色。
hierarchy viewer.bat位于<sdk>/tools/目录下。使用可见:Using Hierarchy Viewer , 示例图如下:

(2) layoutopt
layoutopt是一个可以提供layout及其层级优化提示的命令行,在sdk16以后已经被lint取代,在Windows->Show View->Other->Android->Lint Warnings查看lint优化提示,lint具体介绍可见Improving Your Code with lint。

转载自:http://blog.csdn.net/banketree/article/details/12506763

Android 布局优化小结相关推荐

  1. 深入探索Android布局优化(上)

    前言 成为一名优秀的Android开发,需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样~. Android的绘制优化其实可以分为两个部分,即布局(UI)优化和卡顿优化,而布局优化的核心 ...

  2. Android布局加载慢,Android布局优化(四)X2C — 提升布局加载速度200%

    系列文章 前言 在Android布局优化(一)从布局加载原理说起中我们说到了布局加载的两大性能瓶颈,通过IO操作将XML加载到内存中并进行解析和通过反射创建View.这里介绍一种避免运行时通过IO操作 ...

  3. android listview viewstub,Android布局优化之ViewStub控件

    ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View.虽然Android开发人员基本上都听说过,但是真正用的可能不多. ViewStub可以理解成一个非常轻量级的Vie ...

  4. 一篇文章搞定《Android布局优化》

    ------<一篇文章搞定Android布局优化> 前言 为什么要进行布局优化? Android绘制原理 双缓冲机制 布局加载原理 布局加载优化的一些方法介绍 AsyncLayoutInf ...

  5. android布局优化方案,Android启动优化-布局优化

    Android启动优化-布局优化 安卓应用开发发展到今天,已经成为一个非常成熟的技术方向,从目前的情况看,安卓开发还是一个热火朝天的发展,但高级人才却相对较少,如今移动互联网的开发者也逐渐开始注重插入 ...

  6. android layout include merge,Android 布局优化之include与merge

    Android 官方提供了三个用来优化布局的标签,分别是include.merge与ViewStub,其中ViewStub是动态加载视图到内存,大家可以查阅:Android UI布局优化之ViewSt ...

  7. android 减少布局层级,Android 布局优化

    布局优化主要从以下几点进行着手 减少布局层次 和 复杂度 优化绘制流程 按需加载布局 减少布局层次 和 复杂度 首先我们可以通过以下工具分析界面布局的结构 查看布局树工具:Hierarchy View ...

  8. Android 布局优化

    在开发过程中我们经常说性能优化,但性能优化是一个比较宽泛的概念.在Android开发中性能优化可能包括:Java代码优化, 算法优化, SQLite优化, 布局优化等.那么这篇博客就来总结并分享下An ...

  9. android布局优化 工具,详解Android布局优化

    怎样才能写出优秀的Android App,是每一个程序员追求的目标.那么怎么才能写出一个优秀的App呢?相信很多初学者也会有这种迷茫.一句话来回答这个问题:细节很重要.今天我们就从最基础的XML布局来 ...

最新文章

  1. myeclipse 引用jar包中代码,做断点
  2. 太酷了!Linux的30 个实例详解 TOP 命令!
  3. python orm框架sqlalchemy_python orm 框架中sqlalchemy用法实例详解
  4. 判断页面打开的浏览器信息
  5. 【c语言】用指针变量输出一维数组中的数据
  6. OC中方法与函数的区别
  7. java编写flash相册的制作软件,Flash电子相册制作工具(Amazing Flash Gallery Maker)
  8. 一些鼠标指针图案大全和美化 20+
  9. python爬取大众点评数据_小试Python——爬虫抓取大众点评上的数据
  10. Lunar Pro for Mac v5.2.2 – 实用的外接显示器屏幕亮度调节工具
  11. 淘宝API item_search_similar - 搜索相似的商品
  12. Oracle 自带管理工具
  13. 消费者行为学的典型营销案例
  14. 阿里云API-python脚本开发-云监控数据对接nightingale监控
  15. CentOS7.x Sysbench 测试mysql数据库性能(version:sysbench-1.1.0)
  16. 【云原生 | Kubernetes 系列】---CephFS和OSS
  17. Airbnb短租数据分析报告
  18. Docker实现原理之 - OverlayFS实现原理
  19. 数据库原理之候选码的判断方法
  20. 概率初步(1 Juin, 2019)

热门文章

  1. UOS与Deepin OS区别详解
  2. 黑客挂马紧盯娃娃 儿童节育儿教育网站被挂马
  3. ubuntu18.04 安装 ros2 foxy
  4. 如何给Linux服务器安装瑞星,手把手教你制作瑞星Linux杀毒光盘
  5. 每日新闻:科学家称人工智能可以迅速发展自己的偏见;工信部:贯彻落实企业上云政策...
  6. Web前端技术基础实验报告二之格式化文本、段落与列表
  7. 扫盲贴:手游圈行业术语汇总
  8. 莫听穿林打叶声,2022年SSD行业回顾与展望
  9. 基于SSM+vue的前后端分离小项目(用户后台管理系统的实现)
  10. postgresql 11.2 下载