How you can go wrong with the new Data Binding API

The last couple of days were full of excitement in the Android world as Google I/O took place. In no surprise, some of the rumours came true and Android M was announced (with a possibility to download the preview as last year), which comes with a bunch of new APIs.

One of the new API that caught my eye is the Data Binding Library. In short, it lets you bind data directly into your layouts by having a POJO - variable declaration pair. Let's take the example from the official documentation:

Assuming we have a simple User POJO defined as:

public class User {
   public final String firstName;
   public final String lastName;
   public User(String firstName, String lastName) {
       this.firstName = firstName;
       this.lastName = lastName;
   }
}

and a layout in which we want to display the user's first and last name. With Data Binding we can directly reference the user's fields in the layout:

activity_main.xml

<xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
  <data>
      <variable name="user" type="com.example.User"/>
  </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.firstName}"/>
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.lastName}"/>
   </LinearLayout>
</layout>

A binding class will be generated based on the name of the layout file (in this case ActivityMainBinding) which you can use in your activity to actually tell the layout which user object to use:

ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
User user = new User("Test", "User");
binding.setUser(user);

So far so good, nothing really complicated or hard to comprehend. In a way, this removes a bit of boilerplate code (not having to findViewById() or setText()). My first impression was that this is the aim of this API.

Things start to take a slippery slope

Going forward with reading the documentation, you can see that you can do a lot more with Data Binding than to simply remove the need of findViewById() and attach simple data to your views.

You can actually import java classes in your layouts and use them directly in place:

<xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
  <data>
      <import type="android.view.View"/>
  </data>
  <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView
          android:text="@{user.lastName}"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>
   </LinearLayout>
</layout>

Here we import the Android View class and use it directly in the layout in order to specify the visibility state of the view. You can even import your own class and use it:


<data>
    <import type="com.example.MyStringUtils"/>
    <variable name="user" type="com.example.User"/>
</data>
…
<TextView
   android:text="@{MyStringUtils.capitalize(user.lastName)}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

Or even Collections :


<data>
    <import type="android.util.SparseArray"/>
    <import type="java.util.Map"/>
    <import type="java.util.List"/>
    <variable name="list" type="List"/>
    <variable name="sparse" type="SparseArray<String>"/>
    <variable name="map" type="Map<String, String>"/>
    <variable name="index" type="int"/>
    <variable name="key" type="String"/>

…
android:text="@{list[index]}"
…
android:text="@{sparse[index]}"
…
android:text="@{map[key]}"

And you can do a lot more with having Observable Fields, Observable Collections or custom bindings. All of these can be found in the official documentation.

This is more than binding simple data to your views and avoiding the boilerplate code. To me, this is actually mixing business logic in your UI layouts. Your views should be as dumb as possible, adhering to the Single Responsibility Principle with the only responsibility to show data. This could lead to a complicated, cluttered and unclean codebase.


We've seen some of the examples of the Data Binding API. I'm sure that this API was created in order to ease the developers' work and avoid boilerplate, but one can overuse it and accidentally create chaos in his code. Mixing Java in your view code has never been a good idea. Does JSP ring a bell?

I'm looking forward to seeing the different use cases in which developers will make use of the Data Binding API. How would you use it?