Jetpack data bindingDataBinding

DataBinding

DataBinding is a technology commonly used in software development for binding data models to user interfaces. Through DataBinding, we can realize automatic updating and two-way binding of data, so that data changes can be automatically reflected on the interface, and user operations on the interface can also be automatically updated into the data model.

In Android development, DataBinding is a technology used to bind views in layout files to data models. By using specific syntax in the layout file, we can bind the properties of the view to the fields or methods in the data model to achieve data display and interaction.

Using DataBinding can simplify code writing and improve development efficiency. It can reduce tedious operations such as findViewById and setText, and can also avoid the problem of inconsistency between the interface and data caused by manually updating data.

By using DataBinding, we can more conveniently manage the relationship between the interface and data, improving the readability and maintainability of the code. At the same time, it also provides a more flexible way to handle interface display and interaction.

DataBinding usage

To use DataBinding in an Android project, you need to add the DataBinding dependency in the project’s build.gradle file and use tags in the layout file to declare the data model. You can then use the @{} syntax to bind views in the layout to properties in the data model.

In the build.gradle file of the app module, add the following plug-in dependencies:

android {<!-- -->
    ...
    dataBinding {<!-- -->
        enabled = true
    }
}

or

android {<!-- -->
    ...
    buildFeatures {<!-- -->
      dataBinding true
    }
}

Here is a simple example showing how to use DataBinding in Android:

<!-- activity_main.xml -->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="user"
            type="com.example.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}" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Update"
            android:onClick="@{() -> user.updateName()}" />
    </LinearLayout>
</layout>
// MainActivity.java
public class MainActivity extends AppCompatActivity {<!-- -->
    private User user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {<!-- -->
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        user = new User("John Doe");
        binding.setUser(user);
    }
}

//User.java
public class User {<!-- -->
    private String name;

    public User(String name) {<!-- -->
        this.name = name;
    }

    public String getName() {<!-- -->
        return name;
    }

    public void updateName() {<!-- -->
        name = "NewName";
    }
}

In the above example, the layout file activity_main.xml uses the DataBinding syntax to bind the text of TextView and the click event of Button. In MainActivity, bind the layout file to the Activity through the setContentView method of the DataBindingUtil class, and pass the User object to the layout file.

When the Button is clicked, the updateName method of the User object is called to update the value of the name attribute. Since TextView is bound to the name attribute, the text of TextView will automatically update to the new value.

Use in Fragment

In the Fragment’s layout file, use tags to wrap the layout file, and set the data tag to define data-bound variables and expressions. For example:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="viewModel"
            type="com.example.ViewModel" />
    </data>
    
    <!-- The layout content of Fragment -->
    ...
</layout>

In the Fragment, use the inflate method of the DataBindingUtil class to load the layout file and obtain the bound instance. For example:

public class MyFragment extends Fragment {<!-- -->
    private MyFragmentBinding binding;
    private ViewModel viewModel;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {<!-- -->
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_my, container, false);
        View view = binding.getRoot();

        //Initialize ViewModel
        viewModel = new ViewModel();

        // Bind ViewModel to layout file
        binding.setViewModel(viewModel);

        return view;
    }
}

Access variables and expressions defined in the layout file through the binding object. For example, data and methods in ViewModel can be accessed through binding.viewModel. You can use DataBinding in Fragment to implement data binding.

Used in Adapter

Using DataBinding in Adapter can easily bind data to each Item view in RecyclerView. Create an internal class ViewHolder in the Adapter of RecyclerView and use DataBinding to bind the layout file of the Item view. In ViewHolder, we can use DataBinding to obtain each View in the layout file and bind data to these Views.

class MyAdapter(private val dataList: List<Data>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {<!-- -->

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {<!-- -->
        val inflater = LayoutInflater.from(parent.context)
        val binding: ItemLayoutBinding = DataBindingUtil.inflate(inflater, R.layout.item_layout, parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {<!-- -->
        val data = dataList[position]
        holder.bind(data)
    }

    override fun getItemCount(): Int {<!-- -->
        return dataList.size
    }

    inner class ViewHolder(private val binding: ItemLayoutBinding) : RecyclerView.ViewHolder(binding.root) {<!-- -->

        fun bind(data: Data) {<!-- -->
            binding.data = data
            binding.executePendingBindings()
        }
    }
}

In the above code, ItemLayoutBinding is a Binding class automatically generated based on the layout file item_layout.xml. We can obtain this Binding object through the DataBindingUtil.inflate() method and pass it to ViewHolder.

In the bind() method of ViewHolder, we bind the data object data to the Binding object and call the executePendingBindings() method to immediately Update UI.

Finally, in Activity or Fragment, we can use this Adapter to set the RecyclerView’s Adapter:

val adapter = MyAdapter(dataList)
recyclerView.adapter = adapter

Each Item view automatically updates based on changes to the data object.

Use of include tag

When using DataBinding, you can reuse layout files through the include tag. The include tag can include one layout file into another layout file to achieve layout reuse. Add an id to the include tag, which can be used directly in DataBinding.

<include
    android:id="@ + id/includeData"
    layout="@layout/layout_include_data_item"/>
binding.includeData.includeTvTitle.setText("")
Usage of ViewStub tag

Add an id to the ViewStub tag. You can use the id directly in DataBinding.

<ViewStub
    android:id="@ + id/stub"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout="@layout/view_stub" />
binding.stub.setOnInflateListener {<!-- --> stub, inflated ->
    // DataBinding
    val dataViewStub: ViewStubDataBinding = DataBindingUtil.bind(inflated)!!
    dataViewStub.tvTitle.setText("Use ViewStub to load DataBinding layout")
}
            
if (!binding.stub.isInflated) {<!-- -->
    binding.stub.viewStub!!.inflate()
}

Summary

DataBinding is a technique used to bind views in layout files to data models. By using specific syntax in the layout file, we can bind the view’s properties to fields or methods in the data model. When the data model changes, the view automatically updates and vice versa.

Using DataBinding can reduce the manual writing of tedious codes such as findViewById() and setText(), and improve development efficiency. At the same time, it can also reduce bugs caused by out-of-synchronization between views and data models and improve code reliability.

DataBinding is a convenient and powerful technology that can simplify the binding process of views and data models in Android development, improving development efficiency and code maintainability.