Android Data Binding with MVVM
In working with mobile applications, a primary concern should always be clean architecture with separated layers. The first layer is Data Persistence which is responsible for fetching data from the internet or from local device storage. The second layer connects data with an interactive presentation: User Interface. Some of the well known architectures, such as MVC, MVP, MVVM, exist to elevate the separation of concerns between the data and UI. Following a known architecture means implementing SOLID principles in a structured way.
At Google I/O in 2015, Android team presented a new data binding support library. This was a new cool thing that reduced the boilerplate code not only for performing view inflation, but also for setting and getting values from views. Android Data Binding also allowed developers to streamline MVVM architecture easier.
Let’s check how it works on the example below to be more aware of the advantages that go with data binding.
Set up Data Binding
Android data binding is an Android Studio IDE built-in feature, and it’s compatible for all Android versions since API 7. The only requirement is to have Gradle 1.5.0-alpha1 or higher version, but you should be good to go if you have a latest version of Android Studio. We enable the data binding in our gradle file:
android { compileSdkVersion 24 buildToolsVersion "24.0.0" dataBinding.enabled = true }
Let’s use an MVVM approach and create a Model for our binding.
Android data binding allows us to make reference in the XML layout to the fields in Java class. To connect our object fields and present its data we need to create a class like below:
public class CustomObject extends BaseObservable { public final ObservableField<String> label = new ObservableField<>(); public final ObservableField<String> value = new ObservableField<>(); public CustomObject(String label, String value) { this.label = label; this.value= value; } }
Our class needs to extend BaseObservable
, which provides a data binding interface for accessing ObservableFields
in the layout file. ObservableField
is primitive container for objects that informs us about changes of its value. This can be helpful while creating some custom converters using BindingAdapters
.
Connecting the Model with XML layout
Creating XML layout works differently with the data binding. The XML layout contains only one child: layout
tag. The layout
tag should have data
tag as its first child, followed by a series of Android UI children. In the data tag, we include the java path to our model and ViewModel classes. In the Android UI tags, we use a data binding expression denoted by @{expression}
for controlling actions in the view, click event listener, user input, etc..
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="model" type="com.your.package.CustomObject" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/label" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@{model.label}" /> <EditText android:id="@+id/value" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@={model.value}" /> </LinearLayout> </layout>
Data in our layout will use CustomModel
, and we will connect both labels and values to views. In order to achieve this, we need to create a data binding variable with the application package path .CustomModel
as a variable type.
To connect ObservableField
to the layout we need to use @{}>
or @={}
for two-way data binding. Two-way binding means simply that our field will be updated whenever the value changes programmatically or by user input.
Connecting Model object with layout binding.
Now it’s time to connect our model to the layout and let the binding magic happen! In order to do that, we need to assign our object to binding reference auto-generated by Android. When we create a data-binding XML layout, Android Studio automatically creates a binding java object for us, denoted by the XML layout name. In this case, we name it ‘MyLayoutBinding’:
MyLayoutBinding myLayoutBinding = MyLayoutBinding.inflate(inflater); CustomObject customObject = new CustomObject(‘my label’, my value’); myLayoutBinding.setModel(customObject);
And that’s it! Now every time you type something in EditText
our ‘value’ will update itself thanks to two-way data binding.
Some facts
This article just shows the very basics of what the new Android Data Binding can do, and how this can save not only time but also lines of boilerplate code. Less code will create a more readable architecture for the project, which will be easier for other developers to follow. For more details I encourage to you check out the Android docs for data binding.