What is Android Data Binding library?

The Data Binding Library is a support library in Android application development which allows binding UI components of the layouts not programmatically rather in a declarative format.

Why use the Android Data Binding library?

Remove boilerplate code

Android Data Binding Library can remove so many lines of boilerplate code. But it may require additional classes too. Therefore, we need to care and keep it in balance while using it.

Read it better

The library increases the readability of the codes. But it absolutely depends on the developer. New developers may find it difficult at first. But once developers get used to it, it looks more readable to them.

Powerful

The code has more power, you can implement whatever you like in code. We can think of it like, implementing a task without data binding is quite long to developers and with data binding, we have the power to implement it using fewer codes.

Faster than findViewById()

We are used to with the method findViewById() to access the UI components of our layouts. But Data Binding is faster than using this.

Auto-generated class

It’s helpful that we don’t need to think of the process to bind every UI component individually (and typecasting). Rather this library will generate classes for UI components automatically. It’s true it will increase the app size, but again only if you have tons of it.

Get started

The Data Binding Library is a support library. Therefore it offers both flexibility and compatibility to previous API levels. For now, we can use it with devices running Android 4.0 (API level 14) or higher. The recommendation is to use the latest Android Plugin for Gradle in the project. However, this library supports version 1.5.0 and higher.

At first, we need to download the library from Support Repository using the Android SDK manager. Then we can configure our project to use a data binding library. To use it, we need to add the element to our build. gradle file of the app module. Let’s go through some codes.

// This is the android section from the file build.gradle (app)

android {

   compileSdkVersion 29
   buildToolsVersion "29.0.1"
   defaultConfig {
   applicationId "com.example.databindinglibrary"
   minSdkVersion 21
   targetSdkVersion 29
   versionCode 1
   versionName "1.0"
   testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
   }
   buildTypes {
   release {
   minifyEnabled false
   proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
   }
   }
 }
We will add the data-binding element now.

// Upon adding the data-binding element
android {
  compileSdkVersion 29
  buildToolsVersion "29.0.1"
  defaultConfig {
  applicationId "com.example.databindinglibrary"
  minSdkVersion 21
  targetSdkVersion 29
  versionCode 1
  versionName "1.0"
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 }

buildTypes {
release {
  minifyEnabled false
  proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
 }
}

// Enable Android data binding library

 dataBinding {
    enabled true
   }
}

So, our data binding library is enabled now. There is a new compiler for generating data binding classes that have been introduced at the Android Gradle plugin version 3.1.0-alpha06. It creates the data binding classes incrementally, which in most cases increases the speed of the build process. To enable it, we need to add the following line at gradle.properties file.

android.databinding.enableV2=true

Let’s use Android Data Binding

Suppose, the below codes are from the current activity layout.

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

<TextView

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
And the activity codes are,
package com.example.databindinglibrary
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<TextView>(R.id.text_view_title).text = getString(R.string.app_name)
    }
}

Now, if we want to add data binding here, we need to introduce <layout> as the root tag. Go through the below codes,

<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Now, open your activity codes. Remove the line with findViewById() method. Following are from our activity,

package com.example.databindinglibrary
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
   class MainActivity : AppCompatActivity() {
      override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)
      }
}

We will introduce a binding object here. The object will be of a binding class that will be auto-generated by the data binding compiler. The auto-generated class will be named from the name of our layout file. If the layout file name is “activity_main”, then the generated class name will be ActivityMainBinding. We will replace the previous setContentView() method of the activity by setContentView() method of a utility class DataBindingUtil. It will inflate the layout, set it to activate and return the binding object which we will keep at our activity/fragment. After initialization, we can easily use this object to access our UI components. Below, we have used our binding object to set the text to our only TextView.

package com.example.databindinglibrary
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.databindinglibrary.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {      
    private lateinit var mBinding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        mBinding.textViewTitle.text = getString(R.string.app_name)
    }
}

Thus, we are getting rid of findViewById() method. Android Data Binding library is providing much flexibility to us.

Use of <data> section
Another way of accessing our UI components is passing the required variables to our layout and setting the values at our layout (.xml) files. Have a look at the below codes,

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <variable name="title" type="String"/>
    </data>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        <TextView
            android:id="@+id/text_view_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{title}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

We have introduced a new tag named <data> here. This is the section where we will declare our variables. Here we have one variable named “title” which is an object of String class. And this variable value is set to our TextView. We will put a @{} and place the variable inside the brackets to use the value of it. We will pass the value to this variable from the activity/fragment. Follow the codes,

package com.example.databindinglibrary
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.databindinglibrary.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
    private lateinit var mBinding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        mBinding.title = getString(R.string.app_name)
    }
}

Use of custom model class

Well, we can use custom model too to set the values to the UI components. Let’s create a custom model class. We name it as Student.

package com.example.databindinglibrary   
data class Student(
   val name: String?,
   val ID: String 
)   

Now, we will re-arrange our layout file to show a student’s name and id. Codes are at below,

<?xml version="1.0" encoding="utf-8"?> 
<layout     
xmlns:android="http://schemas.android.com/apk/res/android"     
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">   
    <data> 
        <variable name="student" type="com.example.databindinglibrary.Student"/> 
    </data>       
<androidx.constraintlayout.widget.ConstraintLayout         
android:layout_width="match_parent"         
android:layout_height="match_parent"         
tools:context=".MainActivity">           
<TextView             
android:id="@+id/text_view_name"             
android:layout_width="wrap_content"             
android:layout_height="wrap_content"             
android:text="@{student.name}"             
android:textSize="18sp"             
android:textStyle="bold"             
app:layout_constraintVertical_chainStyle="packed"             
app:layout_constraintBottom_toTopOf="@+id/text_view_id"             
app:layout_constraintLeft_toLeftOf="parent"             
app:layout_constraintRight_toRightOf="parent"             
app:layout_constraintTop_toTopOf="parent"/>           
<TextView             
android:id="@+id/text_view_id"             
android:layout_width="wrap_content"             
android:layout_height="wrap_content"             
android:layout_marginTop="16dp"             
android:text="@{student.ID}"             
android:textSize="16sp"             
app:layout_constraintBottom_toBottomOf="parent"             
app:layout_constraintLeft_toLeftOf="parent"             
app:layout_constraintRight_toRightOf="parent"             
app:layout_constraintTop_toBottomOf="@+id/text_view_name"/>       
</androidx.constraintlayout.widget.ConstraintLayout>   
</layout>

At the activity, we will create the student object and pass it to our layout now.

package com.example.databindinglibrary
import android.os.Bundle 
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.databindinglibrary.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() { 
  private lateinit var mBinding: ActivityMainBinding 
  override fun onCreate(savedInstanceState: Bundle?) { 
        super.onCreate(savedInstanceState) 
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)           
        val student = Student("Student Name", "Student ID") 
        mBinding.student = student 
   } 
}

Handle null

Auto-generated data-binding codes check automatically if there is any null value. It tries to avoid NPE (Null Pointer Exception). For example, we can pass null as the name of the student and it won’t crash the application as data binding methods handle this.

package com.example.databindinglibrary   
import android.os.Bundle 
import androidx.appcompat.app.AppCompatActivity 
import androidx.databinding.DataBindingUtil 
import com.example.databindinglibrary.databinding.ActivityMainBinding   
class MainActivity : AppCompatActivity() {   
    private lateinit var mBinding: ActivityMainBinding   
    override fun onCreate(savedInstanceState: Bundle?) { 
        super.onCreate(savedInstanceState) 
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)   
        val student = Student(null, "Student ID") 
        mBinding.student = student 
    } 
}

Use of import

Another thing we will focus on the <data> section is we can import reference classes inside the layout file which can be used later to meet use-cases. At first, let’s change the model class a bit. Follow the codes,

package com.example.databindinglibrary   
data class Student( 
    val name: String?, 
    val ID: String, 
    val shouldShow: Boolean 
)

We have added a Boolean field shouldShow which will define if we want to show the student’s name or not. We have used it in the layout.

<?xml version="1.0" encoding="utf-8"?> 
<layout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools">   
   <data> 
        <import type="android.view.View"/> 
        <variable name="student" type="com.example.databindinglibrary.Student"/> 
    </data>   
    <androidx.constraintlayout.widget.ConstraintLayout 
        android:layout_width="match_parent" 
        android:layout_height="match_parent" 
       tools:context=".MainActivity">   
       <TextView 
           android:id="@+id/text_view_name" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:text="@{student.name}" 
            android:visibility="@{student.shouldShow ? View.VISIBLE : View.INVISIBLE}" 
            android:textSize="18sp" 
            android:textStyle="bold" 
            app:layout_constraintVertical_chainStyle="packed" 
            app:layout_constraintBottom_toTopOf="@+id/text_view_id" 
           app:layout_constraintLeft_toLeftOf="parent" 
            app:layout_constraintRight_toRightOf="parent" 
            app:layout_constraintTop_toTopOf="parent"/>   
        <TextView 
            android:id="@+id/text_view_id" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
           android:layout_marginTop="16dp" 
           android:text="@{student.ID}" 
           android:textSize="16sp" 
            app:layout_constraintBottom_toBottomOf="parent" 
            app:layout_constraintLeft_toLeftOf="parent" 
            app:layout_constraintRight_toRightOf="parent" 
            app:layout_constraintTop_toBottomOf="@+id/text_view_name"/>   
    </androidx.constraintlayout.widget.ConstraintLayout>   
</layout>    

And the change of activity codes will be,   
package com.example.databindinglibrary   
import android.os.Bundle 
import androidx.appcompat.app.AppCompatActivity 
import androidx.databinding.DataBindingUtil 
import com.example.databindinglibrary.databinding.ActivityMainBinding   
class MainActivity : AppCompatActivity() {   
    private lateinit var mBinding: ActivityMainBinding   
    override fun onCreate(savedInstanceState: Bundle?) { 
        super.onCreate(savedInstanceState) 
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)   
        val student = Student("Student Name", "Student ID", false) 
        mBinding.student = student 
    } 
}

Get a view from the binding object

To get a view object from the binding object, we will use simply getRoot() method to get the desired view.

package com.example.databindinglibrary   
import android.os.Bundle 
import androidx.appcompat.app.AppCompatActivity 
import androidx.databinding.DataBindingUtil 
import com.example.databindinglibrary.databinding.ActivityMainBinding   
class MainActivity : AppCompatActivity() {   
    private lateinit var mBinding: ActivityMainBinding   
    override fun onCreate(savedInstanceState: Bundle?) { 
        super.onCreate(savedInstanceState) 
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)   
        val student = Student("Student Name", "Student ID", false) 
        mBinding.student = student   
        val view = mBinding.root 
    } 
}

Final Word

Android Data Binding library is really new and quite supportive. It helps us to get more power of our UI components and even it decreases the error rate. Get the demonstrated codes from here. Stay with us. References:

https://github.com/Rifat15913/explore-android-data-binding.git

https://developer.android.com/topic/libraries/data-binding

https://www.vogella.com/tutorials/AndroidDatabinding/article.html

You can also lean android development with Kotlin.

 

Leave a comment