I have a data class which represents the state for my screen:
@Parcelize data class State( @IgnoredOnParcel val list: List<ViewType> = emptyList(), val isLoading: Boolean = false, val isDialogFilterDisplayed: Boolean = false, val filter: Int? = null, val order: String = ORDER_ASC, val year: String = "", val page: Int = 1, val scrollPosition: Int = 0 ): Parcelable My composable looks like:
@OptIn(ExperimentalMaterialApi::class) @ExperimentalCoroutinesApi @Composable internal fun Route( modifier: Modifier = Modifier, viewModel: ViewModel, refreshState: PullRefreshState, onClicked: (links: Links) -> Unit ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() Screen( list = uiState.list, isLoading = uiState.isLoading, page = uiState.page, modifier = modifier, onChangeScrollPosition = viewModel::setScrollPositionState, loadNextPage = viewModel::nextPage, pullRefreshState = refreshState, onClicked = onClicked ) } My problem is anytime any variable in the data class like the position, page etc get updated in the Viewmodel, it triggers a recomposition of the very long complex LazyVerticalGrid in the Screen composable even though the "list" variable isn't changing. I'm a bit perplexed how to prevent these recompositions.
My only solution is to split the state data class into three separate ones where the uiState data class only contains the list variable and nothing else. Then make a PaginationState and stick the page, position in there then a FilterState and stick the order, year, filter in there, This would mean having three different MutableStateFlows in the Viewmodel and would in theory prevent these recompositions. I'm just not sure what is the industry best practice for my use case. Any thoughts and suggestions from experienced compose folks would be very welcome!
ViewTypeis stable and consider switching toImmutableListfromkotlinx.collections.immutable. Beyond that, there may be things you can do insideScreen()to help.LazyVerticalGrid()thinks that your list is changing when you believe it is not.