Skip to content

Additional tips for Data binding

Lake edited this page Nov 13, 2021 · 2 revisions

With Data Binding

<?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="lifecycleOwner"
            type="androidx.lifecycle.LifecycleOwner"
            />
        <variable
            name="itemView"
            type="android.view.View"
            />
        <variable
            name="absoluteAdapterPosition"
            type="Integer"
            />
        <variable
            name="bindingAdapterPosition"
            type="Integer"
            />
        <variable
            name="layoutPosition"
            type="Integer"
            />
        <variable
            name="itemPosition"
            type="Integer"
            />
    </data>
    <ConstraintLayout>
    ...
<layout>

How to inject data when the view is created (e.g, onCreateViewHolder).

Sometimes you want to inject some common data for view holder.
This kind of data cannot be in AntonioBindingModel because it will be bound to a view holder XML at every "onBindViewHolder" moments.
For this situation, You can put additionalVariables in AntonioAdapter with BR variables.

Example

Initialize

 private fun initAdapter(){
     // You also can specify the type of Antonio model for the adapter, if you don't need various view types.
     // e.g., AntonioAdapter<ContentSmallModel>()
      binding.recyclerView.adapter =
          AntonioAdapter<AntonioModel>().apply {
             currentList = viewModel.antonioModels
             additionalVariables = mapOf(BR.someVariableName to someVariableData, BR.someVariableName2 to someVariableData2)
          }
      // Don't forget to set the layout manager to your recycler view :)
      binding.recyclerView.layoutManager = GridLayoutManager(context,4)
      viewModel.onDataSetChanged.observe(this) {
          binding.recyclerView.adapter?.notifyDataSetChanged()
      }
 }

Use them in xml

<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="someVariableName"
            type="io.github.naverz.antonio.sample.antonio.SomeVariableName"
            />
        <variable
            name="someVariableName2"
            type="io.github.naverz.antonio.sample.antonio.SomeVariableName2"
            />
    </data>
    ...
</layout>

LifecycleOwner

LifecycleOwner, which is nearest from the view, will be automatically injected on All of XML inflated from AutoBindingModel in order to use LiveData for the one or two-way binding.

ExecutePendingBindings

Doing some changes to your binding does not mean that it will have an immediate effect on your View. Changing things in binding means that it'll be scheduled those changes to be applied in the nearest future.

But In some cases, You need to apply changes immediately. Then you can implement requireExecutePendingBindings method to return true on your AntonioBindingModel.

e.g,)

data class ContentSmallModel(
    val id: String,
    @DrawableRes val iconRes: Int,
    val price: Int,
    val onClick: (id: String) -> Unit,
    val onLongClick: (id: String) -> Boolean,
    val selectedIds: LiveData<Set<String>>
) : AntonioBindingModel {
    override fun layoutId(): Int = R.layout.view_holder_content_small
    override fun bindingVariableId(): Int = BR.model
    // Implementation
    override fun requireExecutePendingBindings() = true
}

[Caution] It might not be as smooth as without this call, So You'd better implement this method when you really need it.