How to use DataBinding in Android to explain of Kotlin in detail

  • 2021-12-09 10:06:25
  • OfStack

Preface

This question mainly introduces the use of DataBinding in Android App. Data binding is a generic technique that binds and synchronizes a provider's data source with a consumer.

1. Android applications use data binding

1.1 Introduction to DataBinding

Android provides support for writing declarative layouts through DataBinding. This simplifies the code associated with layout and logic to the greatest extent.
Data binding requires modifying files, and the outer layer needs to wrap an layout layout. References to elements and expressions in the layout are written to attributes primarily through @ {} or @ = {} syntax.


<?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="mainModel"
   type="me.ithome.jetpack.model.MainViewModel" /> ① 
 </data>

 <androidx.constraintlayout.widget.ConstraintLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity"> ② 

  <TextView
   android:id="@+id/tv_userinfo"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@{mainModel.userData.toString()}"
   app:layout_constraintBottom_toBottomOf="parent"
   app:layout_constraintLeft_toLeftOf="parent"
   app:layout_constraintRight_toRightOf="parent"
   app:layout_constraintTop_toTopOf="parent" />

  <Button
   android:id="@+id/button"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_marginTop="56dp"
   android:onClick="@{(view) -> mainModel.getClick(view)}"
   android:text="@string/btn_getUserInfo"
   app:layout_constraintBottom_toTopOf="@+id/tv_userinfo"
   app:layout_constraintEnd_toEndOf="parent"
   app:layout_constraintHorizontal_bias="0.498"
   app:layout_constraintStart_toStartOf="parent"
   app:layout_constraintTop_toTopOf="parent" />

 </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

User variables, which define the attributes and classes that can be used in this layout

② Conventional layout

DataBinding creates an Binding class based on layout. This class contains all bindings of layout attributes (defined variables) to related views, and generates setter for data elements in the layout. The generated class name is based on the name of layout (hump name, plus Binding suffix). For example, if the layout name is activity_main. xml, the generated class is ActivityMainBinding. You can go to the inflate layout and data model through this class, and you can also go to the DataBindingUtil class.

DataBindingUtils Load Layout


val mainBindingUtil = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
mainBindingUtil.lifecycleOwner = this

inflate Load Layout (This method can also be used for RecyclerView, ViewPager)


val mainBindingUtil = ActivityMainBinding.inflate(layoutInflater)
setContentView(mainBindingUtil.root)

We choose 1 from 2 of the above two methods, and we all use the first one in Activity.

1.2 How to Enable DataBinding

To use databinding in the Android App project, simply set the following code in the app/build. gradle file:


android {
 ....
 dataBinding {
  enabled = true
 }
}

1.3 DataBinding Click Event Handling

In addition to data transfer, layout processing also deals with click events.

Use mode and ordinary method call 1 sample. For example, I defined the getClick method in MainViewModel. kt


fun getClick(v: View) {
 //TODO
}

Now I want to call the getClick method when Button is clicked, just by adding the following code to the layout file


android:onClick="@{(view) -> mainModel.getClick(view)}"

If you don't need parameters, you can directly


android:onClick="@{() -> mainModel.getClick()}"

If there are other parameters, the corresponding add parameter list


android:onClick="@{() -> mainModel.getClick(args)}"

Other treatments such as onLongClick are the same.

1.4 Use of import

You can import the class through import and call the static method of the class directly.


<data>
 <import type="me.ithome.jetpack.utils.StringUtils" />
 <variable
  name="mainModel"
  type="me.ithome.jetpack.model.MainViewModel" />
</data>

<TextView
 android:text="@{StringUtils.capitalize(mainModel.userData.name)}"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>

1.5 Real-time Refresh of Data

When the data of viewmodel changes, we want the layout to be refreshed at the same time. There is a very simple method, which does not need to inherit BaseObservable. We introduce LiveData to achieve it.


open class MainViewModel : ViewModel() {

  var userData: MutableLiveData<UserInfo> = MutableLiveData()

  init {
    getUserInfo()
  }

  private fun getUserInfo() {
    val user = UserInfo(" Li 4", (10..50).random())
    userData.postValue(user)  // After the data changes, call the postValue , no need to pass observe Listening, layout data will be refreshed automatically 
  }

  fun getClick(v: View) {
    getUserInfo()
  }
}

1.6 Using BindingAdapter

The annotation BindingAdapter can be used to realize that when the attribute value changes, the control state also changes, such as the picture ImageView. When url changes, the control will display different pictures.

You need to define a static method in the static class:


val mainBindingUtil = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
mainBindingUtil.lifecycleOwner = this
0

Note android: src here, which can specify the properties of the control directly or define the properties yourself.


val mainBindingUtil = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
mainBindingUtil.lifecycleOwner = this
1

The loadImage method binds the android: src property, so view and url are passed to loadImage when the value of this property changes.

What if it is a bound custom field? For example, I now bind a custom url.


val mainBindingUtil = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
mainBindingUtil.lifecycleOwner = this
2

Then the layout file reads like this


<ImageView
      android:id="@+id/imageView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/tv_userinfo"
      app:url="@{mainModel.imageUrl}"
      tools:srcCompat="@tools:sample/avatars" />

Summarize

In front, I mainly wrote some basic usages of databinding, and there are many extended usages, so we will continue to talk about them later.


Related articles: