Android Data Binding: Express Yourself

A Bit More Than Field Access

George Mount
Jul 14, 2016 · 3 min read

As discussed in the previous article, you can assign variable values in layout files in Android Studio. In the example, the text for the user’s first name was set with the expression:

android:text="@{user.firstName}"

The User class was declared as a simple Plain Old Java Object (POJO):

public class User {
public String firstName;
public String lastName;
public Bitmap image;
}

Most of your classes don’t use public fields (I hope), and you’ll have accessors for them. Expressions in the layout should be short and easy to read and we didn’t want developers to have to add all those getFirstName() and getLastName() in their expressions — it makes the expressions less readable. The expression parser automatically tries to find the Java Bean accessor name (getXxx() or isXxx()) for your property. The same expression will work fine when your class has accessor methods:

public class User {
private String firstName;
private String lastName;
private Bitmap image;

public String getFirstName() { return firstName; }
public String getLastName() { return lastName; }
public Bitmap getImage() { return image; }
}

If it can’t find a method named like getXxx(), it will also look for a method named xxx(), so you can use user.hasFriend to access method hasFriend().

Android Data Binding expression syntax also supports array access using brackets, just like Java:

android:text="@{user.friends[0].firstName}"

You can also use the brackets for lists and maps as a shortcut to the “get” methods.

It also allows almost all java language expressions, including method calls, ternary operators, and math operations. But don’t go crazy:

android:text='@{user.adult ? ((user.male ? "Mr. " : "Ms. ") + user.lastName) : (user.firstName instanceof String ? user.firstName : "kid") }'

Nobody can read that! And aside from the hard-coded strings, it is going to be hell to maintain. Do yourself a favor and put your complex expressions back into your model so you don’t have to try to unwind what is going on.

Additionally, there is a null-coalescing operator ?? to shorten the simple ternary expressions:

android:text=”@{user.firstName ?? user.userName}”

which is essentially the same as:

android:text=”@{user.firstName != null ? user.firstName : user.userName}”

One really cool thing you can do with binding expressions is use resources:

android:padding=”@{@dim/textPadding + @dim/headerPadding}

That can save a bunch of separate value declarations. How many times do you just want to add or subtract dimensions? The only problem is that it doesn’t (yet) work with styles.

You can also use string, quantity, and fraction formatting following the syntax from Resources methods getString, getQuantityString, and getFraction. You just pass the parameters as arguments to the resource:

android:text=”@{@string/nameFormat(user.firstName, user.lastName)}”

NullPointerException

One very convenient thing is that data binding expressions always check for null values during evaluation. That means that if you have an expression like:

android:text=”@{user.firstName ?? user.userName}”

If user is null, user.firstName and user.userName will evaluate to null and the text will be set to null. No NullPointerException.

This doesn’t mean that it is impossible to get a NullPointerException. If, for example, you have an expression:

android:text=”@{com.example.StringUtils.capitalize(user.firstName)}”

And your StringUtils had:

public static String capitalize(String str) {
return Character.toUpperCase(str.charAt(0)) + str.substring(1);
}

You’ll definitely see a NullPointerException when a null is passed to capitalize.

Importing

In the example above, the expression to capitalize the name was very long. What we really want is to be able to import types so that they can be used as a shortened expression. You can do that by importing them in the data section:

<data>
<variable
name="user"
type="com.example.myapp.model.User"
/>
<import
type="com.example.StringUtils"
/>
</data>

Now our expression can be simplified to:

android:text=”@{StringUtils.capitalize(user.firstName)}”

What Else?

Expressions are pretty much Java syntax with the few exceptions mentioned above. If you think it will work, it probably will, so just give it a go.

If you have any detailed questions, check out the Binding Syntax section of the Data Binding Guide:

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium