1. 背景知识
推荐先看完Android官方博客对于标签的介绍。
http://android-developers.blogspot.com/2009/03/android-layout-tricks-3-optimize-by.html
文章介绍了的两种使用方式:
(假设XML布局A中include了XML布局B,A称为调用者,B为被调用者)
第一种就是include的调用者父布局使用了FrameLayout,被调用者的父布局也是FrameLayout,两个FrameLayout的属性都相同,因此可以通过将把调用者XML的根tag设置为merge的方式,将被调用者直接添加到调用者的父布局中,达到减少层级的作用;另一种则是自定义View控件时,通过手动inflate含有merge标签的XML布局来减少层级(这个使用较小)。
从中,我们了解到merge的原理在于:调用者检测到merge标签,会直接吧被调用者的merge标签内的所有子View直接添加到A中调用处的父布局中。因此include、merge的搭配使用并不仅仅限与FrameLayout,只不过要考虑到如下的限制:
由于RelativeLayout使用较多,因此接下来以RelativeLayout为例,测试使用merge标签能否在不破坏被调用者的ui结构前提下,依然减少层级。
2.测试对RelativeLayout使用merge减少层级
1.MainActivity的布局
<?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">
<include layout="@layout/include_with_merge" />
<TextView
android:id="@+id/reference"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="reference" />
</RelativeLayout>
2.include_without_merge布局
<?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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="without_merge"/>
</RelativeLayout>
结果如图:
3.include_with_merge布局
<?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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="with_merge"/>
</merge>
结果如图:
4.include_with_merge_with_reference布局
<?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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/reference"
android:layout_alignLeft="@id/reference"
android:text="with_merge_with_reference"/>
</merge>
结果如图:
3.结论
遇到标签后的操作类似于: 根布局(rootView)会对merge标签中的所有子View直接调用rootView.addView()方法。因此如例子所示,即便是LinearLayout、RelativeLayout都可以在merge后保证之前XML内设置的属性,只不过这些属性所参考的父布局变成了rootView,这样必然导致在编写过程中的难度,因为还得考虑调用merge标签处的根布局布局。
对于开发者来说,如果过分使用这种方式来减少LinearLayout、RelativeLayout,反而不是一件好事。因为标签本身是解耦和了,如果在加上则又将的XML布局与被include处的父布局相连接起来,这样会丧失include的初衷。因此Android也仅仅建议使用merge来降低系统提供的FrameLayout和开发者自己编写的FrameLayout之间的层级。