In part 1 of this blog series, I explained how to use Android's data binding library, how to use the binding class to access the view references, and how to use binding objects. I provided an example that showed a simple way to bind the data object to a text view. In part 2 of this series, I will explain how this binding works and how to create a custom binding.
How Does the Binding Magic Happen?

Although the DataBiding library seems very complex, it's actually very simple. To understand how the binding works, we need to dive into the BindingAdapter annotation. This annotation is responsible for connecting the view and the value to set. To create this connection you have to define a name for this binding, which will be the XML attribute. So every time that this attribute is used, the method that has this annotation declared will be called.

The library looks for those attributes whose values are defined using the DataBinding tag (@{value}). This is how the attribute is interpreted as a binding one and not as a normal one. The custom attributes--the ones that don't exist--should be added on XML using the "app" namespace; you don't need to declare the name with that namespace, but if you do, you will get some warning saying that this tag will be ignored.

Imagine the following scenario using the code below:

The "customAttribute" is declared with "@{myObject.text}" as the value. In this example, the library interprets the "customAttribute" as a DataBiding one, because it's receiving the tag (@{}) as the value. So the library will look and call for any annotation that has "customAttribute" as its name.

But, in the example given in part 1, I didn't create any BindingAdapter, so how does it work? It's really simple. The DataBinding library already has a lot of implemented adapters, such as "android:text," "android:digits," "android:inputType," etc. We can find all the adapters by looking at the DataBinding source code.

How to Create a Custom Binding

Creating a binding is pretty simple: first, create a static and public method. The first parameter of this method will be the view object that will use the binding tag. In this example, our binding tag will be "TextView." The second parameter will be the object, which can be an integer, string, resource id, or any kind of object that you want. Next, simply add the annotation to the method, passing a string as the parameter; this string is the XML attribute name, which we'll call "text" in our example:

The third and last step is the binding implementation: inside the method, you need to bind the view with the object. Let's use the examples mentioned before--we created a method with TextView as the first parameter. The second parameter will be a string, and the attribute will be "text." Now, all we have to do is to set the text inside the TextView, calling the specific setter.

The BindingAdapter can also declare more than one attribute. For each new attribute added, you have to add a new parameter to the method. For example, let's say you have a custom view and you want to create adapters for three properties: showButton, text, and disabled. In this case, it's possible to create only one method with three parameters for each attribute:

The requireAll param defines whether or not all attributes have to be set. When requireAll is false, the non-declared parameter is set as null. To use in the view, just declare the attributes individually using the same method detailed above.

For simple cases, where the binding object is the same as the setter, you can use the annotation BindingMethod. This annotation has three params: the view class, the attribute name, and the method name. This enables you to avoid a lot of boilerplate code. Look at the example below:

In this example, I created a class that is responsible for declaring all the BindingMethods and BindingAdapters. As you can see, using BindingMethods is cleaner than using BindingAdapters, but only for simple cases. If you want to do any validation, you have to use the BindingAdapter.

The BindingAdapter is the reason that the DataBinding library is so powerful. It presents a lot of possibilities for making the model classes clear and independent of the views. This helps us to code less and to make the data and view connection simpler. I recommend taking a look at the adapter already created by the Google team, which you can see here. Understanding this code will help a lot in understanding how the DataBind works and which adapters already exist.


Marcus Vinicius Corrêa Barcelos

Marcus Vinicius Corrêa Barcelos is an Android Engineer at Avenue Code.