Have you ever looked at someone else’s layout and wondered, “Where does that value get set?” Or maybe you think that eliminating findViewById is a great first step, but there is still too much boilerplate code. Android Data Binding makes these things much easier.

Most of classes we write don’t use public fields, and we have accessors for them. Expressions in the layout should be short and easy to read so we don’t want other developers 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. 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.

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.

Talk to Us