Android Jetpack:Empower your UI with Android Data Binding
Data Binding Library is a support library that enables you to bind UI elements in your layouts to data sources in your app using a declarative style rather than programmatically.
Often times, layouts are declared in activities with code that calls UI framework methods. For instance, the code below calls findViewById()
to look-up for a TextView
widget and bind it to the email
property of the viewModel
variable:
TextView txtView = findViewById(R.id.text_demo);
txtView.setText(viewModel.getEmail());
In the previous article, I discussed extensively on how to accelerate development and eliminate boilerplate code with Android Jetpack. Data Binding is one of the components of Android Jetpack which allows developers to declaratively bind observable data to UI elements. Hence, it removes many UI framework calls in your activities, making them simpler and easier to maintain.
Let’s take a look at a basic Data binding call.
<TextView
android:text="@{viewmodel.userName}" />
The awesome part of data binding is that with just a single line of code, I can bind a username to a textview.
Getting started with DataBinding
The Data Binding Library offers both pliability and broad compatibility — it’s a support library, so you can use it with devices running Android 4.0 (API level 14) or higher.
It’s recommended to use the latest Android Plugin for Gradle in your project. However, data binding is supported on version 1.5.0 and higher
To start using data binding on your android studio:
- Download the library from the Support Repository in the Android SDK manager.
- Configure your app to use data binding, add the
dataBinding
element to yourbuild.gradle
file in the app module, as shown in the following example:
// enable data binding for app here
android {
...
dataBinding {
enabled = true
}
}
Android Studio support for data binding
Android Studio supports several of the editing features for data binding code. For instance, it supports the following features for data binding expressions:
- Syntax highlighting
- References, including navigation
- XML code completion
- Flagging of expression language syntax errors
The Preview pane in Layout Editor shows the default value of data binding expressions if provided. For example, the Preview pane displays the default_value
value on the TextView
widget declared in the following example:
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{person.country, default=default_value}"/>
If you need to display a default value only during the design phase of your app development, you can use tools
attributes instead of default expression values.
Layouts and binding expressions
The expression language provides developers with expressions that handle events dispatched by the views. The Data Binding Library automatically generates the classes necessary to bind the views in the layout with data objects in your project.
As for data binding layout files, these are slightly different and start with a root tag of layout
followed by a data
element and a view
root element. The view element is what your root would be in a non-binding layout file:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="person" type="com.example.Person"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{person.firstName}"/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{person.lastName}"/>
</LinearLayout>
</layout>
The person
variable declared within data
describes a property that may be used within this layout. Also, if you want to use expressions inside your layout, you can call attribute properties using the “@{}
" syntax.
In the example below, the TextView
text is set to the firstName
property of the person
variable:
<variable name="person" type="com.example.Person" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{person.firstName}" />
Let’s try to bind a mock-up data to our existing layout.
Before we do that, you need to take a look at the Person object
public class Person {
public final String firstName;
public final String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
By default, a binding class is generated for each layout file. The name of the class is based on the name of the layout file, converting it to Pascal case and adding the Binding suffix to it. The above layout filename is activity_main.xml
so the equivalent generated class isMainActivityBinding
. This class holds the entire bindings from the layout properties (for instance, the person
variable) to the layout's views and knows how to assign values for the binding expressions. The best practice method to create your bindings is to do it while inflating the layout, as shown in the following sample:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
Person person = new person("Test", "Person");
binding.setPerson(person);
}
You can get the view using a LayoutInflater
MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInflater());
If you are using data binding items inside a Fragment
, ListView
, or RecyclerView
adapter, you may choose to useinflate()
methods of the bindings classes or the DataBindingUtil
class
ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
// or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
Cool bananas!!
In the next article, we will dive into the heart of Data binding and in the end, you will be able to comfortably use this component of Android Jetpack for more complex UI.