Learn with code: Jetpack Compose — Lists and Pagination (Part 1)
Learn to create lists and handle pagination in Jetpack Compose

This is part of a multi-part series about learning to use Jetpack Compose through code. This part of the series will be focusing on building the game listing screen and also covering the test cases for this screen.
Other articles in this series:
Introduction
If you are hearing about jetpack compose for the first time then Google describes it as:
Jetpack Compose is Android’s modern toolkit for building native UI. It simplifies and accelerates UI development on Android bringing your apps to life with less code, powerful tools, and intuitive Kotlin APIs. It makes building Android UI faster and easier.
There are a lot of keywords in the above paragraph like less code, intuitive, faster and easier. One of the main things that is missing is the ease of testing your compose UI. Compose makes it much easier to test each of your individual UI components separately.
I hear what you are saying — enough about compose already!
What is the app which we will be building?

Yes! We will be building a video games discovery app! You can scroll through an infinite list of games, click on the interested game to see all the details and if any videos are available, you will be able to watch them all! We will be using the awesome RAWG API for our games data.
Dissecting the home screen

As you can see, there are 2 main components in this screen. First one is your app bar which has a title and also has search and filter options. The other one is your list which is responsible to show all the games and also to handle pagination. Let’s code!
App bar
We can design our app bar using TopAppBar
.
The top app bar displays information and actions relating to the current screen.
Let’s go ahead and create a simple composable which takes a title and 2 functions for our search and filter clicks as input parameters.
Let’s preview our HomeAppBar
and see what we got so far.

Looks pretty good but it is missing some styling. Let’s go ahead and give a background colour for the app bar and also change the colour of our icons.
Designing an app bar has never been easier! Our final HomeAppBar
will look as follows:

Games List
Our games list is a grid having 2 items in each row. When we think about lists the first thing that comes to mind is the RecyclerView
widget. In compose, we have lazy composables. As you would have guessed, we have LazyColumn
to display a vertical list and LazyRow
to display a horizontal list. But for our particular use case we have another component called LazyVerticalGrid
which helps in displaying items in a grid.
For pagination we can make use of the Paging 3
library which provides compose support.
Lazy components follow the same set of principles as RecyclerView widget.
The Paging Library makes it easier for you to load data gradually and gracefully.
Note: At the time of writing, lazyVerticalGrid is experimental and paging-compose is still in alpha. Both of these apis may change in the future and be different as described in this article.
Let’s first setup our paging library and then start consuming the data in our composable.
Define a data source
PagingSource
is the primary component of our paging 3 library. It is responsible for all our data.
Setup a steam of PagingData
Now that we have our paging source ready, let’s setup the data stream in our ViewModel
. Pager
class helps to expose a stream of paging data as Flow<PagingData<GameResultsEntity>>
from GamesSource
. This flow is emitted every time Pager
fetches new data from our GamesSource
.
Here, the PagingConfig
takes pageSize as an input parameter which defines the number of items loaded at once from the PagingSource
.
Displaying the data
Now that we have setup a data stream in our ViewModel
, all that is left is to collect this stream and display it in our LazyVerticalGrid
. For this, we can use the collectAsLazyPagingItems()
extension function which collects our stream and converts it into LazyPagingItems
.
LazyVerticalGrid
also needs to know the cell information. In our case, since we want 2 fixed columns, we can provide it through the instance of GrideCells.Fixed
.
Let’s combine our app bar and games list and see what we get so far!

We have our list and we have also achieved pagination! All with very few lines of code!
Designing the game item

On top we have our game image, below that we have our game title, and then below that we have our rating. First layout that would come to mind is a Column
but I wanted to showcase the use of ConstraintLayout
in compose so let’s design it using a ConstraintLayout
.
Also, we will be using Coil library for displaying images.
Running it now we get the following:

We have almost reached our end state. Let’s fine tune our screen a little more.
Displaying loading state and error state
Paging library has built in support to display loading state and error state. We can get the loading state from LoadState
object which can be obtained from LazyPagingItems
.
loadState.refresh
is for when the data is loading for the first time and loadState.append
is for every fetch after the first time. Running it now will get us the following:

I will leave the error state to you. Let me know about your design in the comments!
Testing the composables
Now that we have designed our home screen, let’s see how it can be tested.
Testing UIs or screens is used to verify the correct behaviour of your Compose code, improving the quality of your app by catching errors early in the development process.
For all of our tests we will be using ComposeTestRule
— A TestRule
that allows you to test and control composables and applications using Compose.
When you are testing your UI, the 3 important APIs to consider are:
- Finders: Let you select one or more elements
- Assertions: Let you verify if element is displayed or have certain attributes
- Actions: Let you perform certain view actions like click or scroll
Since we designed our app bar first, let’s try and write a test for it.
The test is pretty self-explanatory. We are loading our home app bar and passing “Title” as our title and then asserting that a view with text “Title” is displayed.
I will leave the rest of the tests for the app bar to you. One example for a test case could be to test whether our search and filter icons are displayed in the app bar. Do get creative and try to cover as many tests as possible!
Let’s try and write a test for game list.
There are a few things happening in the test. Firstly, we have mocked our ViewModel
and provided a mocked response for getting the data. Then, we are loading our home screen and asserting that the games are displayed in our list.
Again, I will leave the rest of the tests to you. Use all your creativity and cover as many tests as possible for the screen!
You can find the complete source code with all the tests for the home screen in this repository.
What’s next?
In this post we have designed our game listing screen and also tested the same. In the next post, let’s explore and build the game details screen and also the different UI tests for this screen. See you there:
Thanks for reading! If you liked the article please do leave a clap 👏 and don’t forget to subscribe and follow to get regular updates! :) You can also connect with me on LinkedIn. I would love to see your designs and tests!
We at ShareChat are constantly working on making our apps better across all our clients: Android, iOS and Web. If you are interested in building ShareChat/Moj or solving interesting problems, let us know by applying here!
Additional Resources
- RAWG website to checkout their cool video games API and get your key
- Android Developers website to learn more about Jetpack Compose
- Material Icons to checkout all available icons which can be used in your application
- Coil library for displaying images in jetpack compose
- Android Developers website to dive deeper into lists in jetpack compose
- Android Developers website to understand Paging 3 library better
- Android Developers website to dive deeper into testing in jetpack compose