RecyclerView pagination scroll listener in Android
Tags: android, pagination, recyclerview, coding
Published: 2022-11-28 17:25:20

---
title: RecyclerView pagination scroll listener in Android
published: true
description: Simple pagination scroll listener to implement infinite scrolling of recycler view items in Android.
tags: android, pagination, recyclerview, coding
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ar3b751st61nfbwmo46l.png
# Use a ratio of 100:42 for best results.
# published_at: 2022-11-20 13:09 +0000
---

## What is pagination
Loading a list of items in batches instead of loading all items in a single go is called pagination. When you open the Gmail web app, you see 50 emails by default in a single page. To see the 51st mail, you have to click on next page button.

## Why pagination
Consider in your Gmail account, there are about one thousand plus emails. Loading all a thousand emails at once will have the following drawbacks:
- Database read operation will be very costly. So you will get a list with a great amount of latency.
- After fetching the list, rendering a large number of items in a single go can slow down GUI.

## Ways to use pagination
In Android, there are two ways to implement pagination:
1. Using jetpack's `paging` library. You can see the detailed implementation of the paging library using MVVM in my other blog [Paging with MVVM and coroutines](https://dev.to/mohitrajput987/android-app-with-mvvm-room-paging-koin-coroutine-live-data-gom).
2. Using our own implementation of RecyclerView scroll listener.

## Simple scroll listener
This article focuses on our own implementation. There are many ways to implement logic inside the scroll listener of RecyclerView. I have created a generic implementation of scroll listener which you can simply copy-paste into your code:

```kotlin

/**
 * Created by Mohit Rajput on 20/03/22.
 * Used for the load more functionality.
 */
abstract class PaginationScrollListener(private val layoutManager: LinearLayoutManager) :
    RecyclerView.OnScrollListener() {

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy)
        val visibleItemCount: Int = layoutManager.childCount
        val totalItemCount: Int = layoutManager.itemCount
        val firstVisibleItemPosition: Int = layoutManager.findFirstVisibleItemPosition()
        if (!isLoading() && !isLastPage()) {
            if (visibleItemCount + firstVisibleItemPosition >= totalItemCount
                && firstVisibleItemPosition >= 0
            ) {
                loadMoreItems()
            }
        }
    }

    protected abstract fun loadMoreItems()
    abstract fun isLastPage(): Boolean
    abstract fun isLoading(): Boolean
}
```

Here is an example usage of this scroll listener:

```kotlin

private var isLoadingEmails = false
private val viewModel by viewModels<EmailsViewModel>()

private fun addScrollListener() {
        recyclerView.addOnScrollListener(object :
            PaginationScrollListener(recyclerView.layoutManager as LinearLayoutManager) {
            override fun loadMoreItems() {
                viewModel.fetchEmails()
            }

            override fun isLastPage() = viewModel.isAllEmailLoaded

            override fun isLoading() = isLoadingEmails
        })
    }
```

### Explanation
- When you start loading the list, set `isLoadingEmails` value to `true`. Once loaded, set it to `false`. This can be managed by view state triggered through live data or state flow.
- `viewModel.isAllEmailLoaded` value depends on API call implementation. If your API provides the total count of list items, you can simply implement it as `isAllEmailLoaded = currentList.size == totalListItems`.
- This implementation is for `LinearLayoutManager` only. I will provide an efficient code for `GridLayoutManager` soon.

## Conclusion
Load more or pagination is a widespread concept that almost every app uses. We write the code of the scroll listener again and again. So I created a small generic class that structures the load more so that it can be reused easily. If loading is in progress, it will not make a loading call simultaneously. 
Thanks for the reading. 😊😊😊