Android Data Binding library post

Android Data Binding library tutorial

About Android Data Binding

When we develop an Android application, we must connect data in java code with the xml layout file. A common approach is to use findViewById() or Butter Knife library to bind views and create listeners. After that, we need to manually set values for layout file. To minimize the glue code responsible for binding data, Google released Android Data Binding library. This technique is well-known in many different languages and platforms. Data binding allows to connect data and user events directly in xml file and to automatically update fields in code on base of the user interaction. At the beginning of this tutorial, I’ll depict some Android Data Binding theory. At the end, I’ll create some examples to show amazing pros of Android Data Binding.

Environment configuration

Data binding requires Android 2.1 or higher (API 7+). To fully configure our environment, we need to do only one thing. Let’s open module build.gradle file and add dataBinding with value enabled = true in android section.

build.gradle

That’s all. Now, we can use Android Data Binding library in our project.

Creating layout

After enabling data binding, we need to make some changes in layout files. If we want to use data binding classes generated by compiler, we have to embed main container in <layout> tag.

NOTE: For clarity in every xml layout file, I have ignored layout constraints and other positioning attributes.

activity_main.xml

When we make <layout> as root tag and build the project, we can start using generated binding classes. For layout named activity_main.xml there is generated ActivityMainBinding class. This class is used to set any value in xml file and to access any view with id (naming convention is similar, view with id tv_hello is accessible as tvHello).

Import and variable tags

To use variables or constants, we have to declare them in the layout file. To achieve it, we need to use <import> and <variable> tags and place them in <data> tag. For example, let’s say that we have Product class with fields: name (String), price (float) and discount (int). We want to always display name and price, but also to hide discount label if there is no discount.

activity_main.xml

In lines 6-12 we can see the usage of <data> tag. The use of variable (which can be set in java code) requires name (name used in rest of layout file) and type (path to variable class) parameters; import requires only type. The String class is imported automatically, so we don’t need to import it manually, but in case of View it’s necessary (we need View class to use visibility constants).

Any data binding expression needs to be written in “@{code}” syntax.

For example, if we want to set text in TextView we need to write:

If we pass integer inside android:text, then Android environment will use resource value with this id. To avert errors, we must wrap our variable in String.valueOf() to get the text value of numeric value (lines 29 and 35).

As I mentioned above, we want to hide TextView if there is no discount. Android Data Binding library allows us to use ternary operator (and many other java code syntax), so we can compare discount value and then set visibility of the TextView. Imported earlier View class is now used to set TextView visible or gone:

Binding data

After layout configuration, we can start writing java code. Every xml file with <layout> tag has it’s own counterpart, so after building the project we have access to the generated classes. Let’s say that we are still working with the activity_main.xml file, so generated binding class name is ActivityMainBinding. Getting instance of this class depends on where we want to use data binding. For activity, we have to replace setContentView() method with following syntax:

If we want to use Android Data Binding library within fragment, then layout inflating looks like following:

Now we have access to every variable through generated binding class and we can use one of two methods to bind java code with layout file. In our example, we need to set Product variable, so we can choose the following method:

or use BR (Binding Resources) class:

After this, the Product variable in layout file have been set.

Listeners, methods references and lambdas

Android Data Binding library has more features than <variable> and <import>. We can set listeners (onClick(), onLongClick() etc.), call methods within variables or use lambdas.

Let’s create simple Presenter class for handling events and name it MainPresenter. This class will contain one listener for new button which will be responsible for calculating price with discount and to display it in the Toast. We have to remember that every listener method must have exactly the same parameters as the listener interface method. For exapmle, onClick() must have View parameter, onTextChanged() in turn CharSequence s, int start, int before, int count.

To handle button clicks in presenter we need to do three things:

  1. Create listener method in presenter:
    MainPresenter.java
  2. Pass presenter to view by DataBinding:
    MainActivity.java

    activity_main.xml
  3. Create button and call listener method in xml file:
    activity_main.xml

As you can see above, we call presenter method without passing View parameter. It means that onClick() method takes default list of parameters.

So, how can we calculate the price with discount if we don’t have the Price object in presenter? Of course, we can pass product to presenter by constructor or setter method, but to demonstrate lambdas and non-default parameters in listeners, we will do it in xml.

Writing lambda expressions in xml looks exactly the same as in the java code. Having in mind that onClick() takes View parameter, we can create an expression to call method with one additional product parameter:

Of course we need to change method in presenter to the following:

And that’s all, discount is now displayed in toast.

Observable fields and two way binding

Android Data Binding allows us to do much more than just set text in TextView or create listener in Button. If we want to use EditText and automatically update text variable in java code, we need to use observable fields and two way binding. Observable fields are just simple observable objects in which we store values. They are some base observable classes (ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, and ObservableParcelable) and one generic ObservableField<T>.

Two way binding requires little syntax change in xml, we have to add equals sign to expression, e.g. EditText:

As you can see, I have added new field to presenter called name. This is ObservableField<String> variable which is used to store value from EditText. For clarity, I’m enclosing java code below:

To access value from ObservableField we need to use accessor methods: get() and set(). If observable field is private, we must remember to add getters and setters. 

Summary

This is just a part of features available in Android Data Binding. We can also create converters, adapters and use observable collections. If you want to learn more about this library, please visit official documentation.

If you want check full list of expression language features click here.

In the next article I’ll show you how to combine together data binding and Android Architecture Components ViewModel and Room to create application with Model-View-ViewModel pattern. You can read my previous article to learn more about Room library. If you have any questions, feel free to ask in comments.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>