Home > Enterprise >  How optimize JetPack Compose list performance?
How optimize JetPack Compose list performance?

Time:04-10

I have a simple composable function which contains LazyColumn:

@Composable
fun MyScreen(itemList: List<Item>) {
    LazyColumn {
        intems(itemList) {
            ...
        }
    }
}

Everything works great, but my ViewState(itemList) should change when the scroll reaches some position index. That's why I add the following lines to my composable function:

@Composable
fun MyScreen(itemList: List<Item>) {
    val lazyListState = rememberLazyListState()
    viewModel.onPositionChanged(lazyListState.firstVisibleItemIndex)
    LazyColumn(state = lazyListState) {
        intems(itemList) {
            ...
        }
    }
}

Everything works as I expected, but performance has noticeably deteriorated. How I can fix it?

CodePudding user response:

You have two problems here:

  1. You're reading the state directly in the Composable with lazyListState.firstVisibleItemIndex, this causes continues recompositions - each time any part of lazyListState changes, e.g. on each scrolled pixel.
  2. You're making viewModel.onPositionChanged call directly from composable. It's recommended to make such calls from special side effect functions, read more about the topic in thinking in compose and side effects documentation.

In this case LaunchedEffect with snapshotFlow can be used like this:

LaunchedEffect(Unit) {
    snapshotFlow { lazyListState.firstVisibleItemIndex }
        .collect(viewModel::onPositionChanged)
}

You can also face same problem when you need to update the view depending on the list state. In such case derivedStateOf should be used: it'll cause recomposition only when the calculated value actually changes.

val firstVisibleItemIndex by remember {
    derivedStateOf {
        lazyListState.firstVisibleItemIndex
    }
}
  • Related