Pagination in Jetpack Compose using Paging 3

Believe it or not, but Jetpack Compose is the future of android development. I’ve already published a crash course on jetpack compose so that you can quickly get started with it. In this post, I will walk you through pagination in Jetpack Compose. As you might already know; now we have paging 3 in AndroidX. Paging 3 integrates very cleanly with the existing recommended app architecture and the jetpack libraries. If you are willing to know how to use it with jetpack compose then this article is for you.

Before we start

A lot of other things are needed for this project. For example, I require paginated data, and for this, I am using a dummy API using As the project requires API integration, I am using Retrofit here. I am using many other things; so let’s first list them out.

  1. Retrofit for Network Calls
  2. Coil for Image Loading
  3. Hilt for Dependency Injection
  4. ViewModel and Coroutine Flows

I don’t want to make this article long and complicated and that is the reason I am not going to cover the above-mentioned things. And another reason is I’ve already covered these things. But to make things easier for you I’ve created a repository for the project on GitHub. The repository has two branches, the first one is the start branch, and I would suggest that you should clone the repository and start from the code that is already in the start branch. The finished code can be found in the final branch.

Clone the repository from here.

Now we can move ahead. When you clone the repositories all the dependencies are already added and everything required to get the paginated data from the API is already setup so let’s quickly jump to the main thing.

Creating a Paging Source

The first step requires creating a Paging Data Source, and we do it by writing an implementation of PagingSource<Key, Value> . It includes load()  function where we need to define how to retrieve paged data. In our case we will, call the API to get the data. As you can see in the API I am passing the page value as a query parameter. All the API call implementations are already written in the project that you just cloned. If you go to the project there is a UserRepository implementation that contains the function getUser()  and we need to call this function inside our PagingSource implementation.

The following image defines how the PagingSource loads the paginated data.

paging 3 android

Now let’s define our PagingSource, and for this I’ve created this class.

Now let’s understand the two overridden function defined in the above PagingSource .

  • getRefreshKey() : For simplicity, you can consider the key as the page number, and this function will return the page number that is needed. The page number can be null if no pages have been loaded.
    if prev is null; we are on the first page.
    if next is null; we are at the last page.
    if both are null; nothing has loaded and we are at the initial page.
  • load() : This is the main function that will actually load the paged data. This returns LoadResult<Key, Value> . As you can see here we are calling the getUsers()  from our repository and wrapping the result with LoadResult . And in case of any error, we can return LoadResult.Error .

Now with the help of this PagingSource , we will define a pager inside our ViewModel.


Defining a pager is very easy; just come inside the MainViewModel class and write the following code.

In the above code usersPager is a Flow of PagingData, and we will collect it inside our composable function. The flow is cached in viewModelScope, using a predefined scope helps to avoid memory leaks.

Paginated List

Rendering paginated list is very similar as rendering a normal list. You can check jetpack compose recycler view, to understand it in detail.

As you can see we just need to use collectAsLazyPagingItems()  to collect the flow from viewModel. And to create the list we use the same LazyColumn. One more thing I am doing here is I am displaying the ProgressBar at the bottom when the list loads a new page. And I am also showing an error item at the bottom of the list; if there is any error loading a page. You can use the following composables for these two things.

Now finally in the MainActivity call the User Composable.

Now you can try running the application. It should work. And you can see the working application in the following video tutorial.

Source code can be found in the same repository you just need to switch to a different branch. That is all for this post friends; in case you have any confusion please leave your comments and I will try to help you out. Thank You 🙂

Leave a Comment