How to Use the Paging 3 Library in Android

Paging 3.0 is a major update over the previous versions of Paging Architecture Component of Android.

Vivek Singh
ProAndroidDev

--

Photo by Markus Winkler on Unsplash

Most apps displays a large list of data to the users, but at a particular time the user sees only a small chunk of data in your app, so fetching all the data from the network is not an efficient solution. The solution is to fetch small chunks of data at a time, and as soon as the user reach at the end of the list, then the app will load more data. This is called Paging.

With the release of Android 11 beta, Google also updated the Paging architectural components library for android. Paging 3 greatly simplifies implementing paging in your android app.

What’s New in Paging 3.0

Paging 3.0 is significantly different from the earlier versions of Paging Library. Some of the new features of Paging 3.0 includes:

  • Support for Kotlin coroutines, Flow, as well as LiveData and RxJava.
  • Built in support for error handling, refresh and retry functionality.
  • Built in support for loading state headers, footers and list separators.
  • In memory caching of data, ensures efficient use of system resources.
  • Prevents api request duplication.
  • Improvements to the repository layer, including cancellation support and a simplified data source interface.

Setup Your Project

To use the Paging 3.0 library, add it to your app level build.gradle file.

dependencies {
def paging_version = "3.0.0-alpha03"
implementation "androidx.paging:paging-runtime:$paging_version"
}

If you want to use RxJava or LiveData, you need to also include:

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

// optional - Guava ListenableFuture support
implementation "androidx.paging:paging-guava:$paging_version"

Create a Data Source

Unlike the previous versions of Paging library, in Paging 3.0 we have to implement a PagingSource<Key, Value> to define a data source. The PagingSource takes two parameters a Key and a Value. The Key parameter is the identifier of the data to be loaded such as page number and the Value is the type of the data itself.

MoviePagingSource.kt
  • Notice the overridden load() function is a suspend function so we can make api requests here to get data from a network or a room database easily.
  • The LoadParams object holds the information about the load operation such as key and page size.
  • If the api request is successful, then we will return the response data wrapped in a LoadResult.Page object along with the previous and next keys.
  • If the api request is unsuccessful then we will return the occurred exception wrapped in a LoadResult.Error object.

The figure below shows exactly how the load() function recieves keys from the previous load and provides the keys for the next load.

Photo on Official Docs of Paging 3

Get the PagingData in ViewModel

Now we will create an instance of Pager in our viewmodel to get a stream of data from the MoviePagingSource that we just created.

MovieFragmentViewModel.kt
  • The Pager object calls the load() method from the MoviePagingSource object, providing it with the LoadParams object and receiving the LoadResult object in return.
  • We also have to provide configurations such as pageSize with the PagingConfig object.
  • The cachedIn(viewModelScope) caches the data from the MoviePagingSource to survive the screen orientation changes.

Display data in RecyclerView

First we have to create a RecyclerView adapter class which extends from the PagingDataAdapter. This is the same as a normal RecyclerView adapter. The PagingDataAdapter takes two parameters, the first one is the type of the data(which in our case is the Movie object), and the second one is a RecyclerView.ViewHolder.

MovieAdapter.kt

Finally, in OnActivityCreated() of our fragment, we can collect the data from PagingData and then submit it into our MovieAdapter.

MovieFragment.kt

The RecyclerView list now displays data from the data source and automatically loads more data when we reach at the end of the list.

Display LoadState and Error messages

The Paging 3.0 library has support for displaying loading states and handling errors. The Paging library exposes the loading state for use in the UI through the LoadState object.

  • If the LoadState is a LoadState.NotLoading object, then there is no active load operation and no errors.
  • If the LoadState is a LoadState.Loading object, then there is an active load operation.
  • If the LoadState is a LoadState.Error object, then there is an error.

We can attach a addLoadStateListener() in our MovieAdapter to listen for LoadState updates.

LoadStateListener.kt

In the next article, we learn how to create header or footers to show the loading state in the RecyclerView itself, and then we will learn to create list separators.

Conclusion

The Paging 3.0 architectural components library is a major update over the previous versions of paging library, and it is completely rewritten from the previous versions of Paging library. It has complete support for the Kotlin coroutines and other reactive streams such as RxJava and LiveData. It also has inbuilt error handling functionality and support for managing loading states which makes implementing paging in our app super easy.

--

--