Tutorial

Android RecyclerView Data Binding

Published on August 4, 2022
author

Anupam Chugh

Android RecyclerView Data Binding

In this tutorial, we’ll be discussing and implementing the RecyclerView Using Data Binding in our Android Application.

Android RecyclerView DataBinding

In order to know the basics of Android DataBinding, do visit this tutorial. Data Binding significantly reduces the boilerplate code. Here, we’ll learn how to implement DataBinding with a RecyclerView which has the ViewHolder pattern. Also, we’ll understand how Data Binding makes it easy to generalise the Adapter classes. Finally, we’ll demonstrate how to directly pass the adapter object in the XML.

Getting Started

Add the following code in your app’s build.gradle:

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

Add the following dependency.

implementation 'com.android.support:design:28.0.0'

Project Structure

android recyclerview data binding In the below application we’ll load the data in the adapter rows of the RecyclerView from the XML using the <data>. Also we’ll set the onClickListener methods in the layout rows itself.

Code

The code for the DataModel.java class is given below:

package com.journaldev.androidrecyclerviewdatabinding;

public class DataModel {

    public String androidVersion, androidName;

    public DataModel(String androidName, String androidVersion) {

        this.androidName = androidName;
        this.androidVersion = androidVersion;
    }
}

The code for the activity_main.xml layout is given below:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto">

    <data>
        
    </data>


    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>
</layout>

MainActivity.java

package com.journaldev.androidrecyclerviewdatabinding;

import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;

import com.journaldev.androidrecyclerviewdatabinding.databinding.ActivityMainBinding;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        populateData();
    }

    private void populateData() {
        List<DataModel> dataModelList = new ArrayList<>();

        dataModelList.add(new DataModel("Android Oreo", "8.1"));
        dataModelList.add(new DataModel("Android Pie", "9.0"));
        dataModelList.add(new DataModel("Android Nougat", "7.0"));
        dataModelList.add(new DataModel("Android Marshmallow", "6.0"));

        MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(dataModelList, this);
        binding.setMyAdapter(myRecyclerViewAdapter);
    }
}

The layout for each row of the RecyclerView is defined in item_row.xml.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="model"
            type="com.journaldev.androidrecyclerviewdatabinding.DataModel" />

        <variable
            name="itemClickListener"
            type="com.journaldev.androidrecyclerviewdatabinding.CustomClickListener" />
    </data>

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="@{() -> itemClickListener.cardClicked(model)}"
        app:cardUseCompatPadding="true">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_margin="8dp"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tvAndroidName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{model.androidName}"
                android:textAppearance="@style/TextAppearance.AppCompat.Headline" />

            <TextView
                android:id="@+id/tvAndroidVersion"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{model.androidVersion}"
                android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />

        </LinearLayout>

    </android.support.v7.widget.CardView>

</layout>

Inside the data tag, we pass two variables - a DataModel reference and a reference of the CustomClickListener interface whose method is called in the CardView. The code for the CustomClickListener.java is defined below:

package com.journaldev.androidrecyclerviewdatabinding;

public interface CustomClickListener {
    void cardClicked(DataModel f);
}

The code for the MyRecyclerViewAdapter.java class is given below:

package com.journaldev.androidrecyclerviewdatabinding;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.Toast;

import java.util.List;

import com.journaldev.androidrecyclerviewdatabinding.databinding.ItemRowBinding;

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> implements CustomClickListener {

    private List<DataModel> dataModelList;
    private Context context;

    public MyRecyclerViewAdapter(List<DataModel> dataModelList, Context ctx) {
        this.dataModelList = dataModelList;
        context = ctx;
    }

    @Override
    public MyRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                               int viewType) {
        ItemRowBinding binding = DataBindingUtil.inflate(
                LayoutInflater.from(parent.getContext()),
                R.layout.item_row, parent, false);

        return new ViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        DataModel dataModel = dataModelList.get(position);
        holder.bind(dataModel);
        holder.itemRowBinding.setItemClickListener(this);
    }


    @Override
    public int getItemCount() {
        return dataModelList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public ItemRowBinding itemRowBinding;

        public ViewHolder(ItemRowBinding itemRowBinding) {
            super(itemRowBinding.getRoot());
            this.itemRowBinding = itemRowBinding;
        }

        public void bind(Object obj) {
            itemRowBinding.setVariable(BR.model, obj);
            itemRowBinding.executePendingBindings();
        }
    }

    public void cardClicked(DataModel f) {
        Toast.makeText(context, "You clicked " + f.androidName,
                Toast.LENGTH_LONG).show();
    }
}

In order to pass the data to the XML counterpart we bind it using itemRowBinding.setVariable(BR.model, obj);. executePendingBindings() is important in order to execute the data binding immediately. Otherwise it can populate incorrect view.

Difference between setVariable() and setModel() setVariable() is used in generic circumstances when the type of the data is not known. setModel() is auto-generated. We can use the following instead of holder.bind(dataModel);.

holder.itemRowBinding.setModel(dataModel);

Passing the Adapter instance in RecyclerView XML Using Data Binding

Thanks to data binding we can further reduce the boilerplate code in our MainActivity.java by passing the adapter instance in the XML inside the android:adapter attribute as shown below: activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto">


    <data>

        <variable
            name="myAdapter"
            type="com.journaldev.androidrecyclerviewdatabinding.MyRecyclerViewAdapter" />
    </data>


    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:adapter="@{myAdapter}"
            app:layoutManager="android.support.v7.widget.LinearLayoutManager"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>
</layout>

In the MainActivity.java we can set the Adapter in the following way now:

MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(dataModelList, this);
binding.setMyAdapter(myRecyclerViewAdapter);

So there’s no need to even initialize RecyclerView in the Activity class. The output of the above application in action is given below: android recyclerview data binding output That brings an end to this tutorial. You can download the project from the link below.

AndroidRecyclerViewDataBinding

Github Project Link

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Anupam Chugh

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
March 5, 2020

I have implemented a recycler view with data binding, in this way, but from the build:Gradle:3.6.1, code is not working:- This is a log which I am getting, java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter

- Shyak Das

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    September 4, 2019

    HI , Please share inverseBinding Adapter and Binding Adapter simple example .

    - Vanshika Saini

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      June 18, 2019

      Really nice explanation and code, the best tutorial i have found about data binding. Thanks for share!!

      - Juan Antonio

        Try DigitalOcean for free

        Click below to sign up and get $200 of credit to try our products over 60 days!

        Sign up

        Join the Tech Talk
        Success! Thank you! Please check your email for further details.

        Please complete your information!

        Become a contributor for community

        Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

        DigitalOcean Documentation

        Full documentation for every DigitalOcean product.

        Resources for startups and SMBs

        The Wave has everything you need to know about building a business, from raising funding to marketing your product.

        Get our newsletter

        Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

        New accounts only. By submitting your email you agree to our Privacy Policy

        The developer cloud

        Scale up as you grow — whether you're running one virtual machine or ten thousand.

        Get started for free

        Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

        *This promotional offer applies to new accounts only.