Reputation: 519
So, i was learning jetpack compose, and trying to make an anime index app which use paging3, pagingcompose,and lazy layout. But, even when i save the lazy state in rememberlazyliststate and rememberlazygridstate, the paging state is always stuck at the end of page 1, i also tried to restore state on compose navigation but still it didn't work as i expected.
Here is my code for flow and ui state on viewmodel:
private val anime: Flow<PagingData<Anime>> = displayedAnimeType.flatMapLatest { type ->
when (type) {
DisplayType.POPULAR -> useCases.getPopularAnime().cachedIn(viewModelScope)
DisplayType.AIRING -> useCases.getAiringAnime().cachedIn(viewModelScope)
DisplayType.UPCOMING -> useCases.getUpcomingAnime().cachedIn(viewModelScope)
DisplayType.SEARCH -> searchedAnime.cachedIn(viewModelScope)
}
}
val explorationScreenState: StateFlow<ExploreScreenState> =
combine(
headerState,
displayedStyle,
displayedAnimeType,
) { headerState: HeaderScreenState, displayedStyle: DisplayStyle, displayedType: DisplayType ->
ExploreScreenState(
headerScreenState = headerState,
displayStyle = displayedStyle,
displayType = displayedType,
anime = anime
)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
initialValue = ExploreScreenState()
)
And here is my code for the lazy layout:
fun ExplorationScreen(
screenState: ExploreScreenState,
onEvent: (ExploreScreenEvent) -> Unit,
onAnimeClicked: (Anime) -> Unit,
modifier: Modifier = Modifier
) {
val pagingAnime: LazyPagingItems<Anime> = screenState.anime.collectAsLazyPagingItems()
val listOfLazyGridState: Map<DisplayType, LazyGridState> = mapOf(
Pair(DisplayType.POPULAR, rememberLazyGridState()),
Pair(DisplayType.AIRING, rememberLazyGridState()),
Pair(DisplayType.UPCOMING, rememberLazyGridState())
)
val listOfLazyListState: Map<DisplayType, LazyListState> = mapOf(
Pair(DisplayType.POPULAR, rememberLazyListState()),
Pair(DisplayType.AIRING, rememberLazyListState()),
Pair(DisplayType.UPCOMING, rememberLazyListState())
)
val lazyGridState = listOfLazyGridState[screenState.displayType]
val lazyListState = listOfLazyListState[screenState.displayType]
Scaffold(
topBar = {
// Top App Bar component
},
modifier = modifier
) { paddingValue ->
if (pagingAnime.itemCount == 0 && screenState.displayType == DisplayType.SEARCH) {
// Show error message when anime is not found on searching
return@Scaffold
}
when (val refreshing = pagingAnime.loadState.refresh) {
is LoadState.Error -> {
// Show error message and retry button
return@Scaffold
}
LoadState.Loading -> {
// Show Loading Progress
return@Scaffold
}
is LoadState.NotLoading -> {
if (screenState.displayStyle == DisplayStyle.LIST) {
LazyListAnime(
lazyListState = lazyListState ?: rememberLazyListState(),
pagingAnime = pagingAnime,
modifier = Modifier.padding(paddingValue),
onAnimeClicked = onAnimeClicked
)
} else {
LazyGridAnime(
lazyGridState = lazyGridState ?: rememberLazyGridState(),
pagingAnime = pagingAnime,
screenState = screenState,
modifier = Modifier.padding(paddingValue),
onAnimeClicked = onAnimeClicked
)
}
}
}
}
}
Is there anything wrong with my way? and also my lazy layout feels really janky compared to xml. Here is the repository since i can't include everything in here: Lelenime Repository. The ui component was on Core:Common module and Feature module
Upvotes: 1
Views: 847
Reputation: 289
This is a known issue in Paging library.
You can use following workaround at the moment
First create a extension function
@Composable
fun <T : Any> LazyPagingItems<T>.rememberLazyListState(): LazyListState {
// After recreation, LazyPagingItems first return 0 items, then the cached items.
// This behavior/issue is resetting the LazyListState scroll position.
// Below is a workaround. More info: https://issuetracker.google.com/issues/177245496.
return when (itemCount) {
// Return a different LazyListState instance.
0 -> remember(this) { LazyListState(0, 0) }
// Return rememberLazyListState (normal case).
else -> androidx.compose.foundation.lazy.rememberLazyListState()
}
}
Then create lazyListState for your lazyPagingItems
val pagingAnimeScrollState = pagingAnime.rememberLazyListState()
Then in your lazyColumn pass this in state
parameter.
This should fix your issue
Upvotes: 0