写点什么

Android 布局优化:include-、merge,android 开发入门与实战作者

用户头像
Android架构
关注
发布于: 刚刚

xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="{activityClass}" >


<includeandroid:layout_width="match_parent"android:layout_height="40dp"layout="@layout/titlebar" />


<Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"a


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ndroid:layout_centerVertical="true"android:onClick="click"android:text="点我。。。" />


</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:


<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" >


<Buttonandroid:layout_width="match_parent"


android:layout_height="wrap_content"


android:layout_marginLeft="20dp"


android:layout_marginRight="20dp"


android:text="登录按钮" />


</LinearLayout>


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


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


activity_login.xml:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="@android:color/holo_blue_light">


<EditText


android:layout_width="match_parent"


android:layout_height="wrap_content"android:layout_marginLeft="20dp"


android:layout_marginRight="20dp"


android:layout_marginTop="40dp"


android:hint="请输入用户名" />


<include layout="@layout/login" />


</LinearLayout>


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



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



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


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


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


<?xml version="1.0" encoding="utf-8"?><merge xmlns:android="http://schemas.android.com/apk/res/android">


<Buttonandroid:layout_width="match_parent"


android:layout_height="wrap_content"


android:layout_marginLeft="20dp"


android:layout_marginRight="20dp"


android:text="登录按钮" />


</merge>


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



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


merge 标签使用注意点:


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


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


LayoutInflate 中源码体现:


public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {synchronized (mConstructorArgs) {


...


if (TAG_MERGE.equals(name)) {if (root == null || !attachToRoot) {throw new InflateException("<merge /> can be used only with a valid "


  • "ViewGroup root and attachToRoot=true");}


rInflate(parser, root, inflaterContext, attrs, false);}...}}


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:


<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:orientation="vertical"android:layout_height="wrap_content" >


<EditTextandroid:id="@+id/weichat_id"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="20dp"android:layout_marginRight="20dp"android:layout_marginTop="10dp"android:hint="请输入微信号" />


<EditTextandroid:id="@+id/address_id"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="20dp"android:layout_marginRight="20dp"android:layout_marginTop="10dp"android:hint="请输入家庭住址" />


</LinearLayout>


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


activity_main.xml:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/holo_blue_light"android:orientation="vertical" >

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android布局优化:include-、merge,android开发入门与实战作者