Android 布局优化
在开发过程中我们经常说性能优化,但性能优化是一个比较宽泛的概念。在Android开发中性能优化可能包括:Java代码优化, 算法优化, SQLite优化, 布局优化等。那么这篇博客就来总结并分享下Android开发中的布局优化。
布局原则
在Android UI布局过程中,通过遵守一些惯用、有效的布局原则,我们可以制作出高效且复用性高的UI,概括来说包括如下几点:
(1)尽量多使用RelativeLayout和LinearLayout, 不要使用绝对布局AbsoluteLayout,在布局层次一样的情况下, 建议使用LinearLayout代替RelativeLayout, 因为LinearLayout性能要稍高一点,但往往RelativeLayout可以简单实现LinearLayout嵌套才能实现的布局。
(2)将可复用的组件抽取出来并通过include标签使用;使用ViewStub标签来加载一些不常用的布局;使用merge标签减少布局的嵌套层次;
RelativeLayout VS LinearLayout
第一条原则说了布局层次一样的情况下LinearLayout比RelativeLayout要好, 但往往RelativeLayout可以简单实现LinearLayout嵌套才能实现的布局。假如需要实现如下布局:
用LinearLayout来实现xml代码如下:
<pre name="code" class="html"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="?android:attr/listPreferredItemHeight"android:padding="6dip"><ImageViewandroid:id="@+id/icon"android:layout_width="wrap_content"android:layout_height="fill_parent"android:layout_marginRight="6dip"android:src="@drawable/icon" /><LinearLayoutandroid:orientation="vertical"android:layout_width="0dip"android:layout_weight="1"android:layout_height="fill_parent"><TextViewandroid:layout_width="fill_parent"android:layout_height="0dip"android:layout_weight="1"android:gravity="center_vertical"android:text="My Application" /><TextView android:layout_width="fill_parent"android:layout_height="0dip"android:layout_weight="1" android:singleLine="true"android:ellipsize="marquee"android:text="Simple application that shows how to use RelativeLayout" /></LinearLayout></LinearLayout>
而用RelativeLayout实现代码如下:
<pre name="code" class="html"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="?android:attr/listPreferredItemHeight"android:padding="6dip"><ImageViewandroid:id="@+id/icon"android:layout_width="wrap_content"android:layout_height="fill_parent"android:layout_alignParentTop="true"android:layout_alignParentBottom="true"android:layout_marginRight="6dip"android:src="@drawable/icon" /><TextView android:id="@+id/secondLine"android:layout_width="fill_parent"android:layout_height="26dip" android:layout_toRightOf="@id/icon"android:layout_alignParentBottom="true"android:layout_alignParentRight="true"android:singleLine="true"android:ellipsize="marquee"android:text="Simple application that shows how to use RelativeLayout" /><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_toRightOf="@id/icon"android:layout_alignParentRight="true"android:layout_alignParentTop="true"android:layout_above="@id/secondLine"android:layout_alignWithParentIfMissing="true"android:gravity="center_vertical"android:text="My Application" /></RelativeLayout>
可以看到用RelativeLayout实现,布局层次明显少了,所以大多数时候优先推荐使用RelativeLayout。
查看布局层次
如何查看布局层次呢?有两种办法:一是通过手机的开发者选项,4.0及以上Android版本可通过设置->开发者选项->显示布局边界打开页面布局显示,看看是否有不必要的节点和嵌套。第二种就是利用SDK自带的UI性能检测工具HierarchyViewer。进入sdk目录下的tools文件夹下,找到HierarchyViewer并运行(此
时保持你的模拟器或真机正在运行需要进行分析的App),双击我们正在显示的这个App所代表的进程。接下来便会进入hierarchyviewer的界面,我们可以在这里很清晰看到正在运行的UI的布局层次结构以及它们之间的关系。大概的显示如下图:
通过布局图我们可以看到根节点DecorView下包含一个LinearLayout, 这个LinearLayout就是包含Activity布局和状态栏的整个屏幕显示的布局父节点,这个LinearLayout有两个子节点, 一个是FrameLayout, FrameLayout就是Activity布局中默认的父布局节点, 这个节点下面就包含了我们自己写的xml布局, 还有一个子节点就是ViewStub,关于这个节点我们在后面会详细介绍。
< include />的使用
在实际开发中,我们经常会遇到一些共用的UI组件,比如带返回按钮的导航栏,如果为每一个xml文件都设置这部分布局,一是重复的工作量大,二是如果有变更,那么每一个xml文件都得修改。还好,Android为我们提供了include标签,顾名思义,通过它,我们可以将这些共用的组件抽取出来单独放到一个xml文件中,然后使用include标签导入共用布局,这样,前面提到的两个问题都解决了。下面以在一个布局main.xml中用include引入另一个布局header.xml为例。
header.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" ><Buttonandroid:id="@+id/button"android:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:layout_above="@+id/text"/><TextViewandroid:id="@+id/text"android:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:layout_alignParentBottom="true"android:text="@string/app_name" /></RelativeLayout>
然后我们在需要引入header的布局xml中通过include导入这个共用布局。
main.xml文件:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="hello world" /><RelativeLayout android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center" ><include layout="@layout/header" /></span></RelativeLayout>
</FrameLayout>
通过这种方式,我们既能提高UI的制作和复用效率,也能保证制作的UI布局更加规整和易维护。
< merge />的使用
merge标签的作用是合并UI布局,使用该标签能降低UI布局的嵌套层次。merge标签可用于两种典型情况:
(1)布局根结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容布局的parent view就是个FrameLayout,所以可以用merge消除只剩一个,这一点可以从上图中看到。
(2)某布局作为子布局被其他布局include时,使用merge当作该布局的根节点,这样在被引入时该根结点会自动被忽略,而将其子节点全部合并到主布局中。
以第一种情况为例,main.xml布局就可以优化如下:
<merge xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><FrameLayout android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="hello world" /><RelativeLayout android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center" ><include layout="@layout/header" /></RelativeLayout></FrameLayout>
</merge>
以第二种情况为例(这个较常用),header.xml布局可以优化如下:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" ><Buttonandroid:id="@+id/button"android:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:layout_above="@+id/text"/><TextViewandroid:id="@+id/text"android:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:layout_alignParentBottom="true"android:text="@string/app_name" /></merge>
这样就不会有多余的FrameLayout和RelativeLayout节点了。
ViewStub标签
viewstub标签同include标签一样可以用来引入一个外部布局,不同的是,viewstub引入的布局默认不会扩张,即既不会占用显示也不会占用位置,从而在解析layout时节省cpu和内存。viewstub常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。
我们新建一个xml文件用来显示一个网络错误时提示信息error.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="wrap_content"android:layout_height="wrap_content" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:background="@android:color/white"android:padding="10dip"android:text="Message"android:textColor="@android:color/black" /></RelativeLayout>
然后在main.xml里面加入ViewStub的标签引入上面的布局:
<merge xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:background="@android:color/darker_gray"android:layout_height="match_parent" >...<ViewStubandroid:id="@+id/error_layout"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"<span style="background-color: rgb(255, 255, 51);">android:layout="@layout/error"</span> /></merge>
在java中通过(ViewStub)findViewById(id)找到ViewStub,通过stub.inflate()展开ViewStub,然后得到子View,如下:
private View errorView;private void showError() {// not repeated infalteif (errorView != null) {errorView.setVisibility(View.VISIBLE);return;}<span style="background-color: rgb(255, 255, 0);">ViewStub stub = (ViewStub)findViewById(R.id.error_layout);errorView = stub.inflate();</span>
}private void showContent() {if (errorView != null) {errorView.setVisibility(View.GONE);}
}
在上面showError()中展开了ViewStub,同时我们对errorView进行了保存,这样下次不用继续inflate。
总结
这篇Blog没有详细介绍HierarchyViewer工具的使用,相信如果对布局原则比较熟练之后,对工具的依赖大大减少,开发效率也会大大的提升。除这些布局原则之外,还需要大家对Android各个组件的属性很熟悉,比如如果要做这么一个布局,一个图片和一个文本的布局,新手们往往会用一个Layout嵌套ImageView和TextView来做, 但是当我们知道TextView有drawableLeft, drawableRight等属性时,那么实现这样的一个布局是非常快速高效的。总之,且学且实践!
Android 布局优化相关推荐
- Android布局加载慢,Android布局优化(四)X2C — 提升布局加载速度200%
系列文章 前言 在Android布局优化(一)从布局加载原理说起中我们说到了布局加载的两大性能瓶颈,通过IO操作将XML加载到内存中并进行解析和通过反射创建View.这里介绍一种避免运行时通过IO操作 ...
- 深入探索Android布局优化(上)
前言 成为一名优秀的Android开发,需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样~. Android的绘制优化其实可以分为两个部分,即布局(UI)优化和卡顿优化,而布局优化的核心 ...
- android listview viewstub,Android布局优化之ViewStub控件
ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View.虽然Android开发人员基本上都听说过,但是真正用的可能不多. ViewStub可以理解成一个非常轻量级的Vie ...
- 一篇文章搞定《Android布局优化》
------<一篇文章搞定Android布局优化> 前言 为什么要进行布局优化? Android绘制原理 双缓冲机制 布局加载原理 布局加载优化的一些方法介绍 AsyncLayoutInf ...
- android布局优化方案,Android启动优化-布局优化
Android启动优化-布局优化 安卓应用开发发展到今天,已经成为一个非常成熟的技术方向,从目前的情况看,安卓开发还是一个热火朝天的发展,但高级人才却相对较少,如今移动互联网的开发者也逐渐开始注重插入 ...
- android layout include merge,Android 布局优化之include与merge
Android 官方提供了三个用来优化布局的标签,分别是include.merge与ViewStub,其中ViewStub是动态加载视图到内存,大家可以查阅:Android UI布局优化之ViewSt ...
- android 减少布局层级,Android 布局优化
布局优化主要从以下几点进行着手 减少布局层次 和 复杂度 优化绘制流程 按需加载布局 减少布局层次 和 复杂度 首先我们可以通过以下工具分析界面布局的结构 查看布局树工具:Hierarchy View ...
- android布局优化 工具,详解Android布局优化
怎样才能写出优秀的Android App,是每一个程序员追求的目标.那么怎么才能写出一个优秀的App呢?相信很多初学者也会有这种迷茫.一句话来回答这个问题:细节很重要.今天我们就从最基础的XML布局来 ...
- Android成长日记-Android布局优化
Android常用布局 1. LinearLayout(线性布局) 2. RelativeLayout(相对布局) 3. TableLayout(表格布局) 4. AbsoluteLayou(绝对布局 ...
最新文章
- android 调用裁切板
- f, (ax1, ax2) = plt.subplots(1, 2, figsize=(20,10)) //该句搭框架,确定输出1行x2列的图象,图片尺寸为20x10英寸
- 「模型解读」深度学习网络只能有一个输入吗
- 【FPGA】SRIO中的关键问题总结(一)SRIO中的关键数据包格式总结
- java的调试工具_2020年最佳Java调试工具(翻译)
- Android Studio使用心得
- glog日志库使用笔记
- 成功必读本:培养人脉的106个技巧
- postgresql集群方案hot standby初级测试(二) ——处理数据能力
- php按按字符串长度分割,支持中文的PHP按字符串长度分割成数组代码_PHP
- 【博士后招聘】清华大学计算机系自然语言处理与社会人文计算实验室面向海内外招聘博士后...
- CAD二次开发——cad查看对象C#:MdgDbg.dll
- Java是什么?Java能干什么工作?
- php居中显示代码,css居中代码是什么
- 使用Motion-Vector实现Real-time人体行为识别
- 程序员们一个一个的都挺神的,堪称 35 岁毕业之后再就业的标兵,不服不行
- RecyclerView之利用ItemDecoration实现万能分割线
- stratum协议原理
- DDR,DDR2,DDR3,DDR4,LPDDR区别
- C语言 随机数实现猜拳游戏