Google suggests using Data Binding Library in our application. With the help of Data Binding Library, we can bind our UI component to data sources using declarative format. The default way of binding data to simple UI component (e.g. TextView, EditText) is findViewById() and setText(). But using Data Binding Library we do not need to do things manually, it results in separation of UI and business logic, and it also removes some of Boiler Plate Code. This tutorial is about Android Data Binding Library, and today we will learn how to use Data Binding Library in our app.
In this post we will fetch some data from Firebase Realtime Database and we will bind the fetched data to our UI components using Android Data Binding Library.
Table of Contents
Basics of Data Binding
Before starting our actual project, let’s first understand some basics about Android Data Binding Library.
Enabling Data Binding
- If you want to use Data Binding in your project, then you need to enable it first. And to do it open your app level build.gradle file. Here inside the android{} block you need to enable data binding. See the code below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
android { compileSdkVersion 27 defaultConfig { applicationId "com.example.iambe.databindingexample" minSdkVersion 15 targetSdkVersion 27 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } //enabling data binding dataBinding { enabled = true } } |
Enabling Data Binding Compiler
For data binding, many classes are generated automatically when you build your project. So initially error is shown, but now Android has the data binding compiler which compiles before the build, which speeds up the development process.
- To enable data binding compiler open your gradle.properties file.
- Inside gradle.properties add the following line.
1 2 3 |
android.databinding.enableV2=true |
The Model
When we are using Data Binding we need models. And this concept is also used in design patterns like MVVM. So model separates our logic and data from the UI components, making it reusable.
For example consider the following model class. (Sometimes it is also colled POJO class).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public class User{ private String name; private String address; private String email; public User(String name, String address, String email) { this.name = name; this.address = address; this.email = email; } public String getName() { return name; } public String getAddress() { return address; } public String getEmail() { return email; } } |
The above class is holding the data of the user, which we need to display in some UI Components. But now for binding the data with UI components we do not need to do it in the java code, instead we will use the declarative format let’s see how.
Data Binding Layout
Now remember one thing, whenever you need to bind data in your layout, the root element will always be <layout>. Inside this element we need to import our Model class using the <data> tag. Let’s see how we do this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="user" type="com.example.iambe.databindingexample.User" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.name}" android:layout_gravity="center_horizontal" android:textAppearance="@style/TextAppearance.AppCompat.Headline" android:textColor="@color/colorPrimaryDark" android:textSize="36sp" /> <TextView android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="@{user.address}" android:textAppearance="@style/TextAppearance.AppCompat.Headline" android:textColor="@color/colorPrimary" /> <TextView android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" android:text="@{user.email}" /> </LinearLayout> </layout> |
- As you can see in the above xml code, first we have the <layout> tag.
- Inside <layout> we have <data> tag. Inside the <data> tag we define all the binding variables needed. For this example we have only one.
- For defining a binding variable inside <data> tag we use the <variable> tag. The <variable> tag has two properties
- name=”variable name”, it is the name of the variable.
- type=”path of variable”, here we define the path of the model.
- After <data> we can design whatever layout we want. Here I have a Simple Vertical LinearLayout.
- But for the data of the UI element, this time we will use @{variable.property}, as you can see in the above code. Here the variable is the name of the variable that we created inside the <data> tag. So in the above example it is @{user.name}.
Observing the Changes
- Usually we need to change the displayed data. But right now our Model do not have this capability. But with the android data binding library we can make our model capable of observing changes.
Using ObservableField
- For this we can use ObservableField<Type>. For example the same model class that we created above can be written as.
1 2 3 4 5 6 7 |
public class User{ public final ObservableField<String> name = new ObservableField<>(); public final ObservableField<String> address = new ObservableField<>(); public final ObservableField<String> email = new ObservableField<>(); } |
- Now while making the object of User class we can set the data using set() method.
1 2 3 4 5 6 |
User user = new User(); user.name.set("Belal Khan"); user.address.set("Kanke, Ranchi"); user.email.set("probelalkhan@gmail.com"); |
Using BaseObservable
- The same model class User can be written as.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public class User extends BaseObservable { private String name; private String address; private String email; @Bindable public String getName() { return name; } public void setName(String name) { this.name = name; notifyPropertyChanged(BR.name); } @Bindable public String getAddress() { return address; } public void setAddress(String address) { this.address = address; notifyPropertyChanged(BR.address); } @Bindable public String getEmail() { return email; } public void setEmail(String email) { this.email = email; notifyPropertyChanged(BR.email); } } |
- BaseObservable: The above class is extending BaseObservable, and BaseObservable implements the mechanism of listener registration.
- Notifying the Data Change: When the class extends BaseObservable, it is the responsibility of the class to notify the property changes. This can be easily done by using @Bindable annotation with getters and notifyPropertyChanged() method, as I did in the above code.
- Here the BR class file is generated automatically while compilation.
Binding the Data
- Finally we need to Bind the data. To do this we can use the following code.
1 2 3 4 5 6 7 8 9 10 |
//creating binding object ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); //creating model object final User user = new User(); //binding the data binding.setUser(user); |
- Here the ActivityMainBinding class is generated automatically by the Android Data Binding Library. If your activity file name is activity_main.xml (which it is by default), then it will create ActivityMainBinding.java. So whatever your layout file name is it will generate the binding class accordingly.
So we have got enough information to implement in our project. So now let’s create an Android Studio Project and implement the Data Binding.
Things You Need to Do First
Before moving further here are the things that you need to do First.
- Create a new android studio project and enable android data binding library as I explained above.
- Create or use an existing firebase project, go to the console and create the following data in realtime database.
- Also change the Firebase Database Rules to public, as we are not going to add any authentication in this example.
- Now add Firebase Realtime Database in your project.
- Also add Glide Image Loading library to your project.
We have learned all these things already so I hope you can do it on your own. But if there is a problem you can follow the Firebase Realtime Database Tutorial First.
Implementing Android Data Binding
- So I hope you have done the things I told you to. Now let’s first create our Model class.
Creating Model Class
- We will create the same User class with a little change, as this time we have image as well in our database, so we will bind the image as well with data binding.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
package com.example.iambe.databindingexample; import android.databinding.BaseObservable; import android.databinding.Bindable; import android.databinding.BindingAdapter; import android.databinding.ObservableField; import android.widget.ImageView; import com.android.databinding.library.baseAdapters.BR; import com.bumptech.glide.Glide; public class User extends BaseObservable { private String name; private String address; private String email; private String image; @Bindable public String getName() { return name; } public void setName(String name) { this.name = name; notifyPropertyChanged(BR.name); } @Bindable public String getAddress() { return address; } public void setAddress(String address) { this.address = address; notifyPropertyChanged(BR.address); } @Bindable public String getEmail() { return email; } public void setEmail(String email) { this.email = email; notifyPropertyChanged(BR.email); } @Bindable public String getImage() { return image; } @Bindable public void setImage(String image) { this.image = image; notifyPropertyChanged(BR.image); } @BindingAdapter({"android:image"}) public static void loadImage(ImageView imageView, String image) { Glide.with(imageView) .load(image) .into(imageView); } } |
- Everything in the above code is already explained except @BindingAdapter. @BindingAdapter is used when we need to define how the data will be binded to views. So here we have used @BindingAdapter({“android:image”}), now whenever we will use android:image property in an ImageView the method will be called, and it will load the Image using Glide, you can also use any other implementation here if you do not want to use Glide.
- The BR will give you error for now, but don’t worry it will be generated when we build our project.
Creating Layout
- Now come to activity_main.xml file and create the layout.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="user" type="com.example.iambe.databindingexample.User" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:image="@{user.image}" android:layout_gravity="center_horizontal" android:layout_width="180dp" android:layout_height="180dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.name}" android:layout_gravity="center_horizontal" android:textAppearance="@style/TextAppearance.AppCompat.Headline" android:textColor="@color/colorPrimaryDark" android:textSize="36sp" /> <TextView android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="@{user.address}" android:textAppearance="@style/TextAppearance.AppCompat.Headline" android:textColor="@color/colorPrimary" /> <TextView android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" android:text="@{user.email}" /> </LinearLayout> </layout> |
- As you can see we have used the declarative method for binding data here, also for the ImageView we have defined the android:image property created with @BindingAdapter.
After creating the layout, go to build->clean project and then build-> rebuild project.
Binding Data
- Finally come to MainActivity.java and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
package com.example.iambe.databindingexample; import android.databinding.DataBindingUtil; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.example.iambe.databindingexample.databinding.ActivityMainBinding; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //creating binding object ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); //creating model object final User user = new User(); //binding the data binding.setUser(user); //reading data from firebase database FirebaseDatabase.getInstance().getReference("user") .addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { user.setName(dataSnapshot.child("name").getValue(String.class)); user.setAddress(dataSnapshot.child("address").getValue(String.class)); user.setEmail(dataSnapshot.child("email").getValue(String.class)); user.setImage(dataSnapshot.child("image").getValue(String.class)); } @Override public void onCancelled(DatabaseError databaseError) { } }); } } |
- If your ActivityMainBinding class is not generated, then make sure you enabled data binding properly, also try restarting Android Studio and rebuilding the project.
- Now you can run your application to check if it is working or not.
- As you can see it is working fine, now if you will change anything on Firebase Realtime Database, changes will be automatically reflected here in your application.
Android Data Binding Library Tutorial Source Code
- Still having some troubles? Don’t worry here is my source code for you. But you need to payme by subscribing to my youtube channel, so use the youtube button to unlock the link and then you can get the source code.
[sociallocker id=1372] Android Data Binding Library Source Code [/sociallocker]
So that’s all for this tutorial friends. Tell me in comments if are having any query regarding Android Data Binding Library. And finally if you found this post useful then please share it with your friends. Thank You 🙂