Pagination in Android with Paging 3

Vipul Saluja
5 min readOct 15, 2021

--

Overview

Paging library helps you to load and show a list of data from a larger data set from local storage or from over the network. This approach helps app to use the network bandwidth and resource of phone efficiently.

You would have used Facebook, Twitter, Instagram, these apps let us scroll indefinitely and this scrolling feature is called Pagination and it helps us in loading and showing a chunk of data with the help of page index and Paging library helps us to achieve this behavior.

For example you want to show a list of 150 users so for doing that you will not load all the data at once, we will do it by loading a small chunk of data and show it to the user.

Advantages

  1. In memory cache
  2. Handling of requesting new data when reach at the end of the list with the help of recycler view
  3. Error handling and refresh capability
  4. Support of flow and live data

Architecture

The paging library integrates directly into the recommended android app architecture. The library operates in 3 layers of app:

  • Repository Layer
  • View Model layer
  • UI layer
Image from Paging3 docs

Repository Layer

Primary component in the repository layer is PagingSource. It defines a source of data and how to retrieve data from it and also it can load data from remote or local data stores.

Another paging library component is RemoteMediator. It handles paging from a layered data source, such as a network data source with a local database cache.

View Model Layer

The Pager provides a public API for creating instances of PagingData based on a PagingSource and a PagingConfig.

PagingData is a component that connects the ViewModel layer to the UI and also a container for a snapshot of a paginated data.

UI Layer

Main UI layer component is PagingDataAdapter, this is a RecyclerViewAdapter that works with the RecyclerView.

Implementation

For implementation of our Paging3 we are going to use the Github API https://api.github.com/users/google/repos which will be used to fetch the list of all the repositories that are created by Google. It can be used with the parameters page and per_page to handle the pagination and the URL for that call will be like this

https://api.github.com/users/google/repos?page=1&per_page=20.

And the final output will be like below image:

To integrate the library we have to add the following dependency into our .gradle file

def paging_version = "3.0.1" //current version at the time

implementation "androidx.paging:paging-runtime:$paging_version"

// alternatively - without Android dependencies for tests
testImplementation "androidx.paging:paging-common:$paging_version"

// optional - RxJava2 support
implementation "androidx.paging:paging-rxjava2:$paging_version"

// optional - RxJava3 support
implementation "androidx.paging:paging-rxjava3:$paging_version"

For simplicity we will just show the name of the repo in our app and for that we will create a model like the below:

data class Repository(val full_name: String)

And the API structure will be like below:

interface NetworkApi {
@GET("users/{username}/repos")
suspend fun fetchRepos(
@Path("username") username: String,
@Query("page") page: Int,
@Query("per_page") size: Int
): List<Repository>
}

Implementing the PagingSource

In order to build our PagingSource, we have to identify the type of the paging key and the type of data to load

PagingSource<Type_Of_Paging_Key, Type_Of_Data_To_Load>

In this case type of paging key is Int, as we have to load data as per the page number and the type of data to load is of Repository type.

We have to get this information from the network and for this NetworkAPI will be used and our PagingSource will look like below

We will have to override two methods here load() and getRefreshKey()

load(params:LoadParams<Int>): This function will be called by the Paging Library to fetch more data to be displayed to the user when user will scroll around. The LoadParams object keep information related to the load operation. We will use the params.key for getting the current page number, if this is the first time when the load is called then it will be null and in that case we have to define the initial page key FIRST_PAGE. And the params.loadSize will return the requested number of items to load.

getRefreshKey(): This method is used for subsequent calls to the load method.

Repository

Now as we have implemented our PageSource now we will build the Repository.

Here we have a fetchRepos() method that will take a username as parameter and will return an object of Flow<PagingData<Repo>>. In this method there is a Pager object which will take the GithubPagingSource that we have created and a PagingConfig with pageSize parameter.

Request data in ViewModel

In the ViewModel we will fetch the list of the repositories by passing the username. Here we will avoid multiple request with same username as below:

Integrate it in the UI

Now we will integrate it in our UI part and first of all we will create an adapter and make it work with the Paging. For that we will extend it with the PagingDataAdapter class of the Paging library, it works in the similar way as RecylerView.Adapter does. It uses DiffUtil on a background thread to compute updates as updated content in the form of new PagingData Objects.

And the Activity code will be like this

With this we have a functional scrolling effect as the Facebook, Twitter. Still some things are there like show empty view and show progress bar when we are fetching the data from the network or retry. To find out how can we do that you can go through the codelab or you can go through the repository with the complete working code that we have used in the example here.

Final Thoughts

Paging library is useful in fetching list of data from the local or remote data source and it also provides the functionality to handle the loading, error or empty state in a very simple way, giving us the more flexibility of that.

References

https://developer.android.com/topic/libraries/architecture/paging/v3-overview

--

--