Creating RecyclerView in Android

Photo by Zdeněk Macháček on Unsplash
Photo by Zdeněk Macháček on Unsplash
When developing an App, it is often we need to display various lists. We can easily implement various lists with Android’s RecyclerView.

When developing an App, it is often we need to display various lists. We can easily implement various lists with Android’s RecyclerView.

The complete code can be found in .

Creating a Project

Create a new Basic Activity project. The Basic Activity project presets MainActivity, FirstFragment, and SecondFragment. We will implement a list in FirstFragment. Therefore, MainActivity and SecondFragment will not be modified.

Creating View and Data for Each Row

Suppose that in each row in the list, there are only two TextViews, one for Key and one for Value. Under res/layout/, add row.xml with the following content:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/keyTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/valueTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Next, we create a data class for the data required by each row. Add RowData, the code is as follows:

package com.waynestalk.androidrecyclerviewexample

data class RowData(val key: String, val value: String)

RecyclerView.Adapter

When RecyclerView is drawing a list, RecyclerView.Adapter is used to provide a view for each row. RecyclerView just draws received views one by one.

Add FirstAdapter, the code is as follows:

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

class FirstAdapter(private val dataset: Array<RowData>) : RecyclerView.Adapter<FirstAdapter.ViewHolder>() {
    inner class ViewHolder(listItemView: View) : RecyclerView.ViewHolder(listItemView) {
        val keyTextView = itemView.findViewById<TextView>(R.id.keyTextView)
        val valueTextView = itemView.findViewById<TextView>(R.id.valueTextView)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val view = inflater.inflate(R.layout.row, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val rowData = dataset[position]
        holder.keyTextView.text = rowData.key
        holder.valueTextView.text = rowData.value
    }

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

The view of a row will be contained in a ViewHolder. So, in FirstAdapter, we declare a ViewHolder inheriting RecylerView.ViewHolder, and parameter listItemView of the constructor is the row view. This listItemView will be set to RecyclerView.ViewHolder.itemView. Then, in the constructor, we will take out the references of all the sub-views in the row.

inner class ViewHolder(listItemView: View) : RecyclerView.ViewHolder(listItemView) {
    val keyTextView = itemView.findViewById<TextView>(R.id.keyTextView)
    val valueTextView = itemView.findViewById<TextView>(R.id.valueTextView)
}

We pass all the data to the constructor of FirstAdapter. After inheriting RecyclerView.Adapter, FirstAdapter must implement three methods:

  • getItemCount(): The total number of rows in the list.
  • onCreateViewHolder(): We will to initiate a row view in this method here.
  • onBindViewHolder(): we will set row data to row view here.

In this way, we have all prepared code for the row part.

RecyclerView

Next, we start to use RecyclerView to draw the list. First of all, first modify fragment_first.xml, we put in <RecyclerView>.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FirstFragment">

    <Button
        android:id="@+id/button_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/next"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/button_first" />

</androidx.constraintlayout.widget.ConstraintLayout>

Add FirstViewModel to provide RowData.

package com.waynestalk.androidrecyclerviewexample

import androidx.lifecycle.ViewModel

class FirstViewModel : ViewModel() {
    val dataset = arrayOf(
            RowData("Side name", "Wayne's Talk"),
            RowData("URL", "https://waynestalk.com"),
    )
}

In FirstFragment, we must create FirstAdapter and pass RowData to it. Then, set FirstAdapter to RecyclerView.

package com.waynestalk.androidrecyclerviewexample

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

class FirstFragment : Fragment() {
    private lateinit var viewModel: FirstViewModel

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        viewModel = ViewModelProvider(this).get(FirstViewModel::class.java)

        val root = inflater.inflate(R.layout.fragment_first, container, false)

        val recyclerView = root.findViewById<RecyclerView>(R.id.recyclerView)
        recyclerView.adapter = FirstAdapter(viewModel.dataset)
        recyclerView.layoutManager = LinearLayoutManager(activity)

        return root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        view.findViewById<Button>(R.id.button_first).setOnClickListener {
            findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
        }
    }
}

Conclusion

Is RecyclerView simple? It helps us draw a list row by row, and we only need to consider how to draw each row. So, most of the logic is in FirstAdapter, it is much simpler!

Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like