Android布局优化:include 、merge、ViewStub的详细总结

本篇博客主要是对上篇博客的补充Android性能优化之UI渲染性能优化, 没有什么新东西,觉得应该是都掌握的玩意,写出来也只是自己做个小小的总结。

一、include的用法以及注意点

在开发Android布局时,我们常将一些通用的视图提取到一个单独的layout文件中,然后使用<include>标签在需要使用的其他layout布局文件中加载进来,比如我们自己App导航栏等。这样,便于对相同视图内容进行统一的控制管理,提高布局重用性。

下面我们以大部分项目中都有的头部导航栏为例,说明一下include的使用,比如我们项目自己统一头部导航栏,抽取布局如下:

titlebar.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
 6      <Button
 7         android:id="@+id/back"
 8         android:layout_width="wrap_content"
 9         android:layout_height="wrap_content"
10         android:layout_alignParentLeft="true"
11         android:layout_centerVertical="true"
12         android:text="返回按钮" />
13
14     <TextView
15         android:id="@+id/title"
16         android:layout_width="wrap_content"
17         android:layout_height="wrap_content"
18         android:layout_centerInParent="true"
19         android:text="提示文字"
20         android:textSize="20sp" />
21
22     <Button
23         android:id="@+id/close"
24         android:layout_width="wrap_content"
25         android:layout_height="wrap_content"
26         android:layout_alignParentRight="true"
27         android:layout_centerVertical="true"
28         android:text="关闭按钮" />
29
30 </RelativeLayout>

很简单,就是左右各一个按钮,中间是一个提示文字。使用也比较简单,如下:

activity_main.xml:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     tools:context="${relativePackage}.${activityClass}" >
 6
 7     <include
 8         android:layout_width="match_parent"
 9         android:layout_height="40dp"
10         layout="@layout/titlebar" />
11
12     <Button
13         android:layout_width="wrap_content"
14         android:layout_height="wrap_content"
15         android:layout_centerHorizontal="true"
16         android:layout_centerVertical="true"
17         android:onClick="click"
18         android:text="点我。。。" />
19
20 </RelativeLayout>
include标签使用还是很简单的,主要通过layout属性声明要引入的布局即可。运行程序界面如下:include标签使用注意点:1,<include>标签当中,可以重写所有layout属性的,如上面include中指定的layout属性将会覆盖掉titlebar中指定的layout属性。而非layout属性则无法在<include>标签当中进行覆写。另外需要注意的是,如果我们想要在<include>标签当中覆写layout属性,必须要将layout_width和layout_height这两个属性也进行覆写,否则覆写效果将不会生效2,一个xml布局文件有多个include标签需要设置ID,才能找到相应子View的控件,否则只能找到第一个include的layout布局,以及该布局的控件。3,如果我们给include所加载的layout布局的根容器设置了id属性,也在include标签中设置了id属性,同时需要在代码中获取根容器的控件对象时,最好将这两个id设置相同的名称!否则,可能获取不到根容器对象,即为null。二、merge的用法以及注意点

merge标签存在的意义是帮助include标签排除多余的一层ViewGroup容器,减少view hierarchy的结构,提升UI渲染的性能。include标签存在着一个不好的地方,可能会导致产生多余的布局嵌套。同样通过一个小demo来说明:

比如项目中有一个公共的登录按钮布局,如下:

login.xml:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="wrap_content"
 5     android:orientation="vertical" >
 6
 7      <Button
 8         android:layout_width="match_parent"
 9         android:layout_height="wrap_content"
10         android:layout_marginLeft="20dp"
11         android:layout_marginRight="20dp"
12         android:text="登录按钮" />
13
14 </LinearLayout>

很简单,就是一个登录的Button。

项目中有登录功能的UI界面如下:

activity_login.xml:

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical"
 6     android:background="@android:color/holo_blue_light">
 7
 8     <EditText
 9         android:layout_width="match_parent"
10         android:layout_height="wrap_content"
11         android:layout_marginLeft="20dp"
12         android:layout_marginRight="20dp"
13         android:layout_marginTop="40dp"
14         android:hint="请输入用户名" />
15
16     <include layout="@layout/login" />
17
18 </LinearLayout>

同样非常简单,运行程序,如下:

看起来没什么问题,其实不知不觉中我们多嵌套了一层布局。我们用工具查看一下此时布局结构:

除去系统布局,我们自己布局最外层是LinearLayout,然后两个并列布局EditText与LinearLayout,在LinearLayout里面是Button登录按钮。

其实这种情况下:在主界面中,<include>标签的parent ViewGroup与包含的layout根容器ViewGroup是相同的类型,这里都是LinearLayout,那么则可以将包含的layout根容器ViewGroup使用<merge>标签代替,从而减少一层ViewGroup的嵌套,提升UI渲染性能。

这里我们把activity_login.xml修改如下:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <merge xmlns:android="http://schemas.android.com/apk/res/android">
 3
 4      <Button
 5         android:layout_width="match_parent"
 6         android:layout_height="wrap_content"
 7         android:layout_marginLeft="20dp"
 8         android:layout_marginRight="20dp"
 9         android:text="登录按钮" />
10
11 </merge>

重新运行程序UI和上面一样效果,通过工具再次查看布局结构;

看到了吧,我们自己布局减少了一层嵌套,从而提升了UI的渲染速度。

merge标签使用注意点:

1,根布局是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity的ContentView父元素就是FrameLayout,所以可以用merge消除只剩一个.

2,因为merge标签并不是View,所以在通过LayoutInflate.inflate()方法渲染的时候,第二个参数必须指定一个父容器,且第三个参数必须为true,也就是必须为merge下的视图指定一个父亲节点.由于merge不是View所以对merge标签设置的所有属性都是无效的.

LayoutInflate中源码体现:

 1     public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
 2         synchronized (mConstructorArgs) {
 3
 4             ...
 5
 6                 if (TAG_MERGE.equals(name)) {
 7                     if (root == null || !attachToRoot) {
 8                         throw new InflateException("<merge /> can be used only with a valid "
 9                                 + "ViewGroup root and attachToRoot=true");
10                     }
11
12                     rInflate(parser, root, inflaterContext, attrs, false);
13                 }
14             ...
15         }
16     }

3,merge标签必须使用在根布局,并且ViewStub标签中的layout布局不能使用merge标签.

ViewStub的用法以及注意点

ViewStub也可以用来加载布局文件,但与include标签完全不同。ViewStub是一个不可见的View类,用于在运行时按需懒加载资源,只有在代码中调用了viewStub.inflate()或者viewStub.setVisible(View.visible)方法时才内容才变得可见。这里需要注意的一点是,当ViewStub被inflate到parent时,ViewStub就被remove掉了,即当前view hierarchy中不再存在ViewStub,而是使用对应的layout视图代替。

同样我们通过一个小demo说明一下,比如我们需要保存一个用户信息,用户名是必须保存的,但是其余信息是不必要的,这是其余信息就可以一开始不显示出来,用户想输入的时候在现实出来。

其余信息布局如下:

otherinfo.xml:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:orientation="vertical"
 5     android:layout_height="wrap_content" >
 6
 7     <EditText
 8         android:id="@+id/weichat_id"
 9         android:layout_width="match_parent"
10         android:layout_height="wrap_content"
11         android:layout_marginLeft="20dp"
12         android:layout_marginRight="20dp"
13         android:layout_marginTop="10dp"
14         android:hint="请输入微信号" />
15
16     <EditText
17         android:id="@+id/address_id"
18         android:layout_width="match_parent"
19         android:layout_height="wrap_content"
20         android:layout_marginLeft="20dp"
21         android:layout_marginRight="20dp"
22         android:layout_marginTop="10dp"
23         android:hint="请输入家庭住址" />
24
25 </LinearLayout>

很简单,没什么其余解释的,主界面布局如下:

activity_main.xml:

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:background="@android:color/holo_blue_light"
 6     android:orientation="vertical" >
 7
 8     <EditText
 9         android:layout_width="match_parent"
10         android:layout_height="wrap_content"
11         android:layout_marginLeft="20dp"
12         android:layout_marginRight="20dp"
13         android:layout_marginTop="40dp"
14         android:hint="请输入用户名" />
15
16     <ViewStub
17         android:id="@+id/viewstub"
18         android:layout_width="match_parent"
19         android:layout_height="wrap_content"
20         android:layout="@layout/otherinfo" />
21
22     <Button
23         android:layout_width="match_parent"
24         android:layout_height="wrap_content"
25         android:onClick="show"
26         android:layout_marginLeft="20dp"
27         android:layout_marginRight="20dp"
28         android:layout_marginTop="10dp"
29         android:text="显示" />
30
31 </LinearLayout>

其余信息界面通过ViewStub引入进来,关于ViewStub主要属性以及方法说明如下:

    • android:layout属性
      加载包含的layout布局文件;
    • android:inflatedId属性
      重写包含的layout布局文件的根容器id;
    • inflate()方法
      setVisible(int)方法作用类似,都可以使内容得以显示,只是inflate()会返回一个View对象,避免了额外使用findViewById()方法获取layout视图对象。

activity中代码如下:

1 public void show(View view){
2         //
3         ViewStub stub = ((ViewStub) findViewById(R.id.viewstub));
4         if(stub!=null){
5             View stubView = stub.inflate();
6             EditText address = (EditText) stubView.findViewById(R.id.address_id);
7             EditText wechatId = (EditText) stubView.findViewById(R.id.weichat_id);
8         }
9     }

好了,运行程序,一开始如下:

点击显示按钮,UI如下:

ViewStub标签使用注意点:

1,ViewStub标签不支持merge标签。因此这有可能导致加载出来的布局存在着多余的嵌套结构,具体如何去取舍就要根据各自的实际情况来决定了。

2,ViewStub的inflate只能被调用一次,第二次调用会抛出异常。

3,虽然ViewStub是不占用任何空间的,但是每个布局都必须要指定layout_width和layout_height属性,否则运行就会报错。

好了,以上就是个人对于include 、merge、ViewStub使用的总结,希望对你有用,即使已经掌握,希望读完此文能温故知新。

原文地址:https://www.cnblogs.com/leipDao/p/8981687.html

时间: 2024-12-13 19:35:08

Android布局优化:include 、merge、ViewStub的详细总结的相关文章

布局重用 include merge ViewStub

在布局优化中,Androi的官方提到了这三种布局<include />.<merge />.<ViewStub />,并介绍了这三种布局各有的优势,下面也是简单说一下他们的优势,以及怎么使用. include标签:实现布局重用 <include />标签能够重用布局文件,以下为标题栏的layout文件 titlebar.xml <FrameLayout xmlns:android="http://schemas.android.com/apk

[Android]Android布局优化之 merge

转载请标明:转载于http://www.cnblogs.com/Liuyt-61/p/6602915.html ----------------------------------------------------------------- >使用merge合并UI布局 作用:合并UI布局,使用该标签能降低UI布局的嵌套层次 场景(1):布局根结点是FrameLayout且不需要设置background或padding等属性,可用merge代替. 场景(2):某布局作为子布局被其他布局incl

Android布局优化之include、merge、ViewStub的使用

本文针对include.merge.ViewStub三个标签如何在布局复用.有效减少布局层级以及如何可以按需加载三个方面进行介绍的. 复用布局可以帮助我们创建一些可以重复使用的复杂布局.这种方式也意味着应用中任何在多个布局文件之间使用的通用布局都可以被提取出来,然后分别进行管理,使用的时候再进行组合.因此当我们在自定义一些View的时候,使用复用布局会更简单方便.在平常开发中使用可以复用的布局文件,不仅仅是因为它可以有效减少布局文件数量,更多的目的在于它更方面我们管理应用,布局复用,在更改某个组

【转】Android布局优化之ViewStub

ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View.虽然Android开发人员基本上都听说过,但是真正用的可能不多. ViewStub可以理解成一个非常轻量级的View,与其他的控件一样,有着自己的属性及特定的方法.当ViewStub使用在布局文件中时,当程序inflate布局文件时,ViewStub本身也会被解析,且占据内存控件,但是与其他控件相比,主要区别体现在以下几点: 1.当布局文件inflate时,ViewStub控件虽然也占据内存,但是相相比于其他控

android 布局优化常用技巧

android对多个模块都要是要的UI逻辑的致辞除了fragment之外,没有别的东西可以支持了, include,merge,viewstub只能支持公用的ui,但是这个通用支持不能包含逻辑(java代码)的. 1.使用include标签 这个标签只是启动重复某个UI xml文件的作用,android框架在解析的时候没有什么优化,唯一的作用就是起到方便管理的作用了. 当解析到 include 标签的时候,就从它的layout属性中拿出 布局文件,解析这个布局,替代include标签的节点 2.

Android性能优化之一:ViewStub

ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View.虽然Android开发人员基本上都听说过,但是真正用的可能不多. ViewStub可以理解成一个非常轻量级的View,与其他的控件一样,有着自己的属性及特定的方法.当ViewStub使用在布局文件中时,当程序inflate布局文件时,ViewStub本身也会被解析,且占据内存控件,但是与其他控件相比,主要区别体现在以下几点: 1.当布局文件inflate时,ViewStub控件虽然也占据内存,但是相相比于其他控

Android布局优化

Android影响布局性能主要是Overdraw(过度绘制),表现在重叠不可见元素的重复绘制会产生额外的开销. Overdraw以颜色划分等级:蓝色:Overdraw1倍:绿色:Overdraw2倍:浅红:Overdraw3倍:暗红;Overdraw4倍以上(需要进行优化). Android布局优化解决措施: 1.合理选择控件 LinearLayout简单易用,效率高,但是使用范围有限. RelativeLayout较复杂,使用范围广,效率稍差. 2.去掉windows默认背景 去掉window

Android 布局优化工具Hierarchy Viewer的使用

网上已经有很多关于Hierarchy Viewer如何使用的文章,这里就不一步步的演示具体怎样使用了,ddna兄的<[Android工具]被忽略的UI检视利器:Hierarchy Viewer>与张兴业的<Android UI 优化--使用HierarchyViewer工具>都写的很棒. Hierarchy Viewer有两个用途,一个是用于分析当前页面视图层级,再者也能分析布局的时间统计(Measrue.Layout.Draw)所需要的具体时间,本篇主要是关注布局时间的统计功能.

我的Android进阶之旅------&gt;Android中的布局优化 include、merge 、ViewStub

1.如何重用布局文件? 可以使用<include>标签引用其他的布局文件,并用android:id属性覆盖被引用布局文件中顶层节点的android:id属性值.代码如下: <!--引用mylayout.xml--> <include android:id="@+id/layout1" layout="@layout/mylayout"/> 2.减少视图层级<merge /> 无论布局文件的根节点是什么,系统都会在上一层