Wednesday, June 13, 2012

Difference between <merge> , <include>and < ViewStub /> tag in Android

The articles showed you how to use the <include/> tag in XML layouts, to reuse and share your layout code. This article explains the <merge /> tag and how it complements the <include/> tag.

We will see when to use <include> and when <merge>.

Its re-use tricks, sort of xml file, elements to file many times.

Define one place and will used in different places.

Create re-usable UI layouts on Android by putting them into an extra XML file and then <include/> them.

In Android XML layout files, each tag is mapped to an real class instance (the class is always a subclass of View, The UI toolkit lets you also use three special tags that are not mapped to a View instance: <requestFocus />, <merge /> and <include/>.

The <include/> element does exactly what its name suggests; it includes another XML layout. Using this tag is straightforward as shown in the below example:

In the <include/> only the layout attribute is required.

<include> basically means 'take that file and paste it's contents here' This way, it’s possible to re-use complete layouts, as opposed to just re-use single widgets.

The <include/> will just include the xml contents in your base xml file as if the whole thing was just a single big file.

< ViewStub />

The < ViewStub /> is a bit different because it is not directly included, and will be loaded only when you actually use it/need it, ie, when you set it's visibility to "true".

This a nice optimization because you could have a complex layout with tons of small views or headers anywhere, and still have your Activity load up really fast.

Once you use one of those views, it'll be loaded.

For example – header.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Header text" />
</LinearLayout>



Main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include android:id="@+id/header"
layout="@layout/header"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>

This will work well, no issue about it. But in order to optimize the code, I have to use <merge> in the layout which gets included. So the top layout should not have a tag <LinearLayout> but it must look like this:

Header.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Header text" />
</merge>

<merge> tag :-

<merge> is used as pseudo parent element to reduce the number of levels in view trees.

<LinearLayot> dont make any differnce when your file is included in other file you mentioned. So its good thing to use merge instead.

Since in XML you must a single parent element and rest of the XML elements should be included in it, you should use merge as single parent element and can avoid adding unnecessary parent layout.

Just avoid 'merge' when you want to apple layout different than layout define in file in which your content is inclded.

It will set the merge element as the higher element in the view hierarchy.

The <merge /> tag was created for the purpose of optimizing Android layouts by reducing the number of levels in view trees.

That's where the <merge /> tag comes in handy.

When the LayoutInflater encounters this tag, it skips it and adds the <merge /> children to the <merge /> parent.

It works perfectly when combined with the <include /> tag.

The <merge /> tag is extremely useful and can do wonders in your code. However, it suffers from a couple of limitations:


<merge /> can only be used as the root tag of an XML layout

When inflating a layout starting with a <merge />, you must specify a parent ViewGroup and you must set attachToRoot to true (see the documentation for inflate(int, android.view.ViewGroup, boolean) method)

Include will simply put the whole viewgroup in there.


With merge:

LinearLayout (root)
|
TextView


With include:

LinearLayout (root)
|
LinearLayout
|
TextView

So you will have an extra LinearLayout in the view hierarchy that you do not need