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:
- 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. - 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:
/**
* 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:
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 totrue
. Once loaded, set it tofalse
. 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 asisAllEmailLoaded = currentList.size == totalListItems
. - This implementation is for
LinearLayoutManager
only. I will provide an efficient code forGridLayoutManager
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. 😊😊😊
Top comments (1)
Very Informative.. Going to use in every application.