Infinite LazyColumn in Jetpack Compose 
Tags: android, kotlin, compose
Published: 2021-06-09 05:45:04

---
title: Infinite LazyColumn in Jetpack Compose 
published: true
description:
tags: android, kotlin, compose
//cover_image: https://direct_url_to_image.jpg
---

Displaying a list of content is one of the most common things that we are required to add to our apps and in my experience the lists are more often than not required to have some sort of pagination. This is a fairly common pattern where we only fetch the items needed at the time. The way we handle that is to show a list with a number of items (say 20) and as the user reaches the end of those first 20 items, we fetch the next 20 items. 

In our app we have an implementation of [RecyclerView.OnScrollListener](https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.OnScrollListener) where we check if we are close to the end of the list and trigger a `loadMore` callback. Now that we are moving to compose I wanted to find a way to do the same pattern and came up with this:

{% gist https://gist.github.com/luismierez/ae5a4f6c84682d6184533ad4587942e2 file=InfiniteListHandler.kt%}

Works similar to our old RecyclerView implementation but now in compose! Let me explain what is going on.

First the parameters:

`listState: LazyListState` as the name implies is the state of the list, which you can get by calling `val listState = rememberLazyListState()`. This state has all the info that we need to observe to create our infinite loading list. It can also be used to control the list, but we aren't using that in here. **REMEMBER:** This same `listState` needs to be passed to the `LazyColumn`

`buffer: Int = 2` This tells our `InfiniteListHandler` how many items **BEFORE** we get to the end of the list to call the `onLoadMore` function. This is technically not needed, but it makes the infinite loading more seamless, since we can  control when to fetch new data and we don't need to show a loading indicator at the end of the list.

`onLoadMore: () -> Unit` This function will get called once the user reaches the load more threshold.

Now to our logic. It's fairly straightforward: we want to call the `onLoadMore` function when the last visible item on the list is within the threshold of our total items in the list minus our buffer. For example:
If we have a list with 20 items, we have a buffer of 4, and with our test device we can see 6 items at a time. As the user scrolls the last visible item index will keep getting higher and higher until it reaches 16, which is our threshold of the last item index (20) minus our buffer (4). At which point the `onLoadMore` will get called and we can fetch and load the next 20 items. Then our list will have 40 items and we will fetch more items once the last visible item index reaches 36, totalItems(40) -  buffer(4). And so on until we have no more items to show.

We can write this in code like:
```
val loadMore = remember {
        derivedStateOf {
            val layoutInfo = listState.layoutInfo
            val totalItemsNumber = layoutInfo.totalItemsCount
            val lastVisibleItemIndex = (layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0) + 1

            lastVisibleItemIndex > (totalItemsNumber - buffer)
        }
    }
```
We use a remembered derived state to minimize unnecessary compositions. See [derivedStateOf](https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#derivedStateOf(kotlin.Function0)) for more info.

But inside we use the `listState` to get the `totalItemsNumber` and the `lastVisibleItemIndex` which we add 1 to, to make it match the total count. We then check that `lastVisibleItemIndex` is greater than our `totalItemsNumber` minus our `buffer`.

There is one last thing that we need to get this working, and that is that we need to observe changes to the `loadMore` `State`. We do that like so:
```
LaunchedEffect(loadMore) {
        snapshotFlow { loadMore.value }
            .distinctUntilChanged()
            .collect {
                onLoadMore()
            }
    }
```

We now have a fully working `InfiniteListHandler` that will notify you whenever you are at the end of the list, or close to it depending on your buffer. And to use it you can do something like:

{% gist https://gist.github.com/luismierez/ae5a4f6c84682d6184533ad4587942e2 file=InfiniteList.kt%}

Happy Composing!