Android Core

Android Data Binding Tutorial

This post describes one of the most interesting feature in Android recently introduced and still in beta version: Android Data Binding. Using data binding, you create a link between the presentation layer (the app UI) and the underlying data model that holds the information you want to show. The UI widgets content like TextView, EditText and so on are somehow bound to the data stored in java class. Every time the data changes the UI widget bound to it is updated, so that you don’t have to worry anymore to update the UI by yourself. If the app does not use Android data binding, it is necessary to find the view and update the content.

Setup Android data binding

As told before, this feature is still in beta version, so as the first thing let’s set the right dependencies in the top level build.gradle:

dependencies { 
  classpath "com.android.tools.build:gradle:1.3.0"
  classpath "com.android.databinding:dataBinder:1.+"
}

by the way, make sure you downloaded gradle 2.4. Now the dependencies are ready and it is time to modify build.gradle in the app:

apply plugin: 'com.android.databinding'

How to use Android data binding

Now that the environment is ready, it is possible to code our Android app. As example, we will create a simple weather app that shows the temperature and other information, in this case to show to data the app will use the data binding.

As the first thing, we create the layout, that will be very simple but it will contains some important things we should notice:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="data" type="survivingwithandroid.com.androiddatabinding.model.Data" />
    </data>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" >


    <android.support.v7.widget.Toolbar
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/toolbar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:background="@color/primary"
        android:elevation="4dp"
        app:theme="@style/ThemeOverlay.AppCompat.Dark"/>


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:layout_below="@id/toolbar"
        android:text="@{data.city}"
        android:textSize="18dp"
        android:id="@+id/weather_icon"/>

    <ImageView
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_centerInParent="true"
        android:src="@{data.icon}"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="@{data.descr}"
        android:layout_marginTop="10dp"
        android:layout_below="@id/weather_icon"/>


    <GridLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="15dp"
        android:rowCount="1"
        android:columnCount="4"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true">

        <TextView android:id="@+id/temp"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:text="@{data.temp}"
            android:layout_row="0"
            android:layout_column="0"
            android:layout_gravity="center"
            />

        <TextView android:id="@+id/press"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:text="@{data.pressure}"
            android:layout_row="0"
            android:layout_column="1"
            android:layout_gravity="center"
            />

        <TextView android:id="@+id/hum"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:text="@{data.humidity}"
            android:layout_row="0"
            android:layout_column="2"
            android:layout_gravity="center"
            />

        <TextView android:id="@+id/wind"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:text="@{data.wind}"
            android:layout_row="0"
            android:layout_column="3"
            android:layout_gravity="center"

            />
    </GridLayout>
</RelativeLayout>
</layout>

As root of the app UI layout there is the layout, and then the variable we want to use in our layout are declared (line 3-5). It is important to declare these variables because they will be used in the binding process. At line 4, it is stated that the variable data is the type of survivingwithandroid.com.androiddatabinding.model.Data that contains the data we want to show. In other world this class is a POJO that is bound the UI. In the TextView widgets, the value of each field of the POJO class is bound to the corresponding android:text so the value is shown automatically.

Binding variable to the object

Now the layout is ready and it is possible to bind the class field to the UI widget. In onCreate method we get the reference to the current layout of the Activity in a different way compared to the usual way:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.setData(data);
        ....
    }

where data is defined as:

private Data data = new Data(); //survivingwithandroid.com.androiddatabinding.model.Data;

Notice that at line 5 we set the activity layout and then we resolve the variable used in the layout. If we run the app in this way, we notice that the UI data is updated only once at the beginning, when the underlaying class field, bound to the UI, changes the UI does not reflect the change. This happen because it is necessary create a listener between the UI and the data field.

The first step is that the our POJO Data class extends BaseObservable:

public class Data extends BaseObservable {
  ....
}

Now it is necessary to bind the single class field to the UI, for example for temperature field:

public class Data extends BaseObservable {
.. 
  @Bindable
  public String getTemp() {
    return temp;
  }

  public void setTemp(String temp) {
    this.temp = temp;
    notifyPropertyChanged(BR.temp);
  }
  ..
}

The @Bindable annotation is used to make a reference between the UI and the field and the notifyPropertyChanged informs the listener that the underlaying filed is changed and it is necessary to update the view. Running an example, using the Android data binding the result is:

device-2015-08-25-223618

 

Conclusion

As we have noticed Android data binding is a very interesting and powerful feature and it can simplify a lot app building. Anyway it is still in beta version and there are some small problems: for example even if i tried to update the ImageView using the same way and setting the resource id it did not work. Is it my mistake?!!

Reference: Android Data Binding Tutorial from our JCG partner Francesco Azzola at the Surviving w/ Android blog.

Francesco Azzola

He's a senior software engineer with more than 15 yrs old experience in JEE architecture. He's SCEA certified (Sun Certified Enterprise Architect), SCWCD, SCJP. He is an android enthusiast and he has worked for long time in the mobile development field.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button