background-shape

Do you have a large list of data to show to the users of your application?

Want a flexible and developer and user friendly way to show the data?

Then RecyclerView is the right choice.

RecyclerView is an advanced version of ListView that is more powerful and flexible.

It is a ViewGroup which is the successor of ListView and GridView including improvement on both of them.

As the name suggests, RecyclerView recycle the views which are out of visibility of user. For example, if user scrolled down to the item number 6 or 7 then items at position 1,2 or 3 would be cleared from the memory to reduce memory consumption.


Pre-requisites

  • Basic knowledge of xml and kotlin

  • Comfortable with classes and objects

  • Should know use of ViewBinding


Components required to setup RecyclerView

  • Model - The data to be shown to the user

  • XML layout - For how to show data to the user

  • Adapter - To bind the data to the RecyclerView

  • ViewHolder - Holds the reference of the view that has to be dynamically modified during the execution of the program


Now let’s dive into the code step by step

Create a new project:

  • Go to File>New>New Project

  • Select Empty Activity and click Next

  • Give your project a suitable name and enter package name (or leave it as default)

  • Select Kotlin as Language and choose Minimum SDK (you can get help from Help me choose)

  • Click Finish

  • After some processing time, the Android Studio main window will appear

Create Model

  • Create a new Kotlin class

    • Right click the package in the Project window

    • Choose New>Kotlin Class/File

    • Select Data Class from class type options

    • Enter name as FoodItem and press enter

  • Do not worry about the error in the parenthesis of the data class

  • Add fields (name and price) for our model

Code for our model class is:

data class FoodItem(val name:String, val price:Float)

Create xml layout for items

  • Right click res/layout and select New>Layout Resource File

  • Give name to the file as food_item_layout and click OK

  • Copy paste this code to the file:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#0000FF"
        android:layout_margin="6dp"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <TextView
            android:id="@+id/foodItemNameTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:textColor="#FFF"
            android:text="Food Item 1"
            android:layout_margin="10dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>
    
        <TextView
            android:id="@+id/foodItemPriceTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#FFF"
            android:text="Rs. 200"
            android:layout_marginEnd="10dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="@id/foodItemNameTV"
            app:layout_constraintBottom_toBottomOf="@id/foodItemNameTV"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  • In activity_main.xml add this code:

    Set layout for the recyclerView in main activity

    <?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=".MainActivity">
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/foodItemsRV"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

Initialize ViewBinding

  • Open app level build.gradle file

  • In android section add this code

buildFeatures{
    viewBinding true
}
  • Now click Sync Now and wait to complete the build process

Set up adapter for recyclerView

Now this is where our data will connect to the views

  • First create a new kotlin class and named it as FoodItemAdapter with parameters Context and MutableList<FoodItem>

  • Now create an inner class FoodItemViewHolder - The ViewHolder for recycler view

  • Code for the inner class:

    class FoodItemViewHolder(foodItemLayoutBinding: FoodItemLayoutBinding)
            : RecyclerView.ViewHolder(foodItemLayoutBinding.root){
    
    }
    
  • Extend FoodItemAdapter with RecyclerView.Adapter<FoodItemAdapter.FoodItemViewHolder>()

  • Move your cursor to the error in the adapter class and press Alt+Enter and select Implement members to implement base class members of the adapter

  • A window will be opened, select all the members from the list and click OK

    These are the member functions

    • onCreateViewHolder - This method is for creating viewHolder

    • onBindViewHolder - This method is for binding our data to views

    • getItemCount - For how many items we have to display

  • Add this code to onCreateViewHolder

    val binding = FoodItemLayoutBinding.inflate(LayoutInflater.from(context),parent,false)
    return FoodItemViewHolder(binding)
    
  • Create a function bind(foodItem: FoodItem) in the FoodItemViewHolder and bind data to the views here

  • This is the code:

    private val binding = foodItemLayoutBinding
    
    fun bind(foodItem: FoodItem){
        binding.foodItemNameTV.text = foodItem.name
        binding.foodItemPriceTV.text = "Rs. ${foodItem.price}"
    }
    
  • Now add this code to the onBindViewHolder member function

    val foodItem = foodItemList[position]
    holder.bind(foodItem)
    
  • In getItemCount just add this line - return foodItemList.size

This is the complete code for our adapter
class FoodItemAdapter(private val context: Context, private val foodItemList:MutableList<FoodItem>)
    : RecyclerView.Adapter<FoodItemAdapter.FoodItemViewHolder>() {


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FoodItemViewHolder {
        val binding = FoodItemLayoutBinding.inflate(LayoutInflater.from(context),parent,false)
        return FoodItemViewHolder(binding)
    }

    override fun onBindViewHolder(holder: FoodItemViewHolder, position: Int) {
        val foodItem = foodItemList[position]
        holder.bind(foodItem)
    }

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


    class FoodItemViewHolder(foodItemLayoutBinding: FoodItemLayoutBinding)
        : RecyclerView.ViewHolder(foodItemLayoutBinding.root){

        private val binding = foodItemLayoutBinding

        fun bind(foodItem: FoodItem){
            binding.foodItemNameTV.text = foodItem.name
            binding.foodItemPriceTV.text = "Rs. ${foodItem.price}"
        }

    }
}

All set with the adapter class

Initialize adapter in the MainActivity class

  • Populate the list of food items that will be shown in RecyclerView

    • Create a property foodItemsList as MutableList<FoodItem> and initialize the list

    • Create a function populateList() and call it in onCreate() of activity class after setContentView()

    • Add this code in the method:

      for (i in 1..15){
           val name = "Food Item $i"
           val price = (100 * i).toFloat()
      
           val foodItem = FoodItem(name = name, price = price)
      
           foodItemsList.add(foodItem)
      }
      
  • Now initialize adapter and layout manager

    • Create a property adapter as FoodItemAdapter and make it lateinit

    • Create a function setUpAdapter() and call it after populateList()

    • Add this code to this function:

      adapter = FoodItemAdapter(this,foodItemsList)
      b.foodItemsRV.adapter = adapter
      b.foodItemsRV.layoutManager = LinearLayoutManager(this)
      
    • The default orientation of the recyclerView is vertical, to change orientation to horizontal use this :

      b.foodItemsRV.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
      
    • Optional, to add a divider line between the views:

      b.foodItemsRV.addItemDecoration(DividerItemDecoration(this,DividerItemDecoration.VERTICAL))
      

Now done with the setting up adapter in the activity

Tip: If you want to add, delete or edit items from the data

  • First update the foodItemsList and then notify adapter about the change you made in the list at a specific position

    • For delete item:

      • In list - foodItemList.removeAt(position)

      • Notify adapter - notifyItemRemoved(position)

    • For add item:

      • In list - foodItemList.add(position, foodItem)

      • Notify adapter - notifyItemInserted(position)

    • For edit item:

      • In list - First remove the item foodItemList.removeAt(position) then add new item foodItemList.add(position,newFoodItem)

      • Notify adapter - notifyItemChanged(position)

  • To notify adapter outside the adapter class, use instance of the adapter - adapter.notifyItemInserted(position)


Now its time to run the application

Don’t know how to run application? See this

The source code for the application is available at github

There’s much more to RecyclerView than what is covered in this post, but with this brief overview, you should be able to create your own custom RecyclerView.

Thank you for reading 🙌🏼

Happy coding😀

BTW, I solve real-world problems by building useful apps. Have a look at our portfolio.

Connect with me on Github and LinkedIn