1. 程式人生 > >Android Data Binding: That Thing

Android Data Binding: That Thing

Android Data Binding: That <include> Thing

When layouts <include> other <layout>s

In the last article you saw how easy it is to avoid using findViewById with Android Studio 1.5 and higher. This is essentially the View Holder pattern as described here:

I showed how to use Android Studio to generate a class that acts as a View Holder for a single layout file, but what about included layouts? What about merged included layouts?

It turns out that those are also supported, but each layout file generates a different class. Here is an example:

hello_world.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>

<TextView
android:id="@+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<include
android:id="@+id/included"
layout="@layout/included_layout"
/>
</LinearLayout
>
</layout>
included_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/world"
/>
</layout>

You would access the two different TextViews this way:

HelloWorldBinding binding =
HelloWorldBinding.inflate(getLayoutInflater());
binding.hello.setText(“Hello”);
binding.included.world.setText(“World”);

The pattern for included files follows the same pattern as for Views: the ID of the <include> tag is used as its field name in the class. The included layout has generated its own class with its own fields for the Views in its layout. Any IDs that are shared between different layout can be easily distinguished by the developer. For example, if you include the same layout twice:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>

<TextView
android:id="@+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<include
android:id="@+id/world1"
layout="@layout/included_layout"
/>
<include
android:id="@+id/world2"
layout="@layout/included_layout"
/>
</LinearLayout>
</layout>

The two “world” TextViews can be accessed easily:

HelloWorldBinding binding =
HelloWorldBinding.inflate(getLayoutInflater());
binding.hello.setText(“Hello”);
binding.world1.world.setText(“First World”);
binding.world2.world.setText(“Second World”);

Remember to give the include tag an ID or no public field will be given to it. Also, remember to use the outer <layout> for layouts that you want to have fields generated. This triggers the preprocessing step that allows it to associate the Views with the fields and generate a class.

If you look into the generated classes, you’ll see that they use the same ones for any time they are included. For example, if you have a goodbye_world.xml class that includes included_layout.xml, only one class is generated for it.