Android RecyclerView And DataBinding with Kotlin

DataBinding binds data directly to the UI of your App.

Sounds fascinating!! So let's learn by doing it.

Step 1:

Enable DataBinding in your App

In build.gradle add

android{ 
...
buildFeatures {
dataBinding true
}
}

Step 2:

In activity_main.xml

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

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

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Wrap your previous constraint layout into <layout> component.

A binding class is generated on its own based on the name of the layout file(here, activity_main.xml), converting to Pascal case, and suffixing “Binding” to it (ActivityMainBinding).

Step 3:

Create a data class for populating the cards of recyclerview

class User(var title: String, var description: String)

Step 4:

Create cards for Recyclerview as card_view.xml

<?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">
<data>
<variable
name="user"
type="com.example.recyclerview.bindingdata.User" />
</data>

<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:cardBackgroundColor="#C8FAFF"
app:cardCornerRadius="4dp"
app:cardElevation="3dp">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/text_view_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:gravity="center_horizontal"
android:text="@{user.title, default = DataBinding}"
android:textSize="18dp" />

<TextView
android:id="@+id/text_view_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:gravity="center_horizontal"
android:text="@{user.description, default = Android_development}"
android:textSize="18dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</layout>

Here also, you have to wrap the Cardview into component.

The Binding class generated will be .

In order to bind your data to UI, you have to create a variable of class “User” under the tag.

Where type is defined as package name +“.”+ classname

<data>
<variable
name="user"
type="com.example.recyclerview.bindingdata.User" />
</data>

We can access member variables of into XML using @{} annotation.

android:text="@{user.title, default = DataBinding}"

Where default is the data that will be shown for preview while creating xml. Databinding(above) is not a variable it’s just a word, passed without any conversion.

In case you want to add a button to the card_view, you can directly define attribute and link it to a custom function(defined in User class).

android:onClick=”@{()->user.clickbutton()}”

Where is defined in the User class. Whenever click action is performed function will be called.

You can’t use TextChangedListeners or FocusChangedListeners here, because they are not allowed with databinding. Instead, use LiveData

Step 5:

Moving Towards Adapter, create a class which contains an inner class that extends

class UserAdapter {

class ViewHolder(private val binding: CardViewBinding) : RecyclerView.ViewHolder(binding.root) {

fun bind(user: User?) {
binding.user = user
binding.executePendingBindings()
}
}
}

ViewHolder will get the View in its constructor from .

binding.user = user

We are initializing the user variable inside our binding(card_view.xml) class.

is important to execute the data binding immediately. Otherwise, it can populate an incorrect view.

Step 6:

Extend UserAdapter with and implement all the methods.

Class UserAdapter(private val userList : ArrayList<User>) : RecyclerView.Adapter<UserAdapter.ViewHolder>(){

class ViewHolder(private val binding: CardViewBinding) : RecyclerView.ViewHolder(binding.root) {

fun bind(user: User?) {
binding.user = user
binding.executePendingBindings()
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val itemBinding: CardViewBinding = CardViewBinding.inflate(layoutInflater, parent, false)
return ViewHolder(itemBinding)
}

override fun getItemCount(): Int {
return userList.size
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(userList[position])
}
}

Pass a list of users to the Adapter for displaying in recyclerview. Now inflate the layout and bind each instance of to your row in and

Step 7:

You have to use in also to get access of and set adapter.

class MainActivity : AppCompatActivity() {

lateinit var mMainBinding: ActivityMainBinding
var mUserList : ArrayList<User> = ArrayList()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mMainBinding = DataBindingUtil.setContentView(this,
R.layout.activity_main)
setupRecyclerView()
}
}

Now, your MainActivity is also done, let's set our recyclerview

Initialize mUserList, create adapter and set it to recyclerview

private fun setupRecyclerView()
{
mMainBinding.recyclerView.layoutManager = LinearLayoutManager(this)
with(mUserList){
add(User("GitHub","Learning Portal"))
add(User("Google","Knows Everything"))
add(User("Facebook","Social media platform"))
add(User("Instagram","Connecting people"))
}
val adapter = UserAdapter(mUserList)
mMainBinding.recyclerView.adapter = adapter
}

All set, you are ready to go now!

Hope This will help you.

Android Developer