It’s a Compose Multiplatform project. I have a screen with BottomBar
component.
fun HomeScreen(mainNavController: NavHostController) {
val homeViewModel = koinViewModel<HomeViewModel>()
val navController = rememberNavController()
val items = listOf(BottomBarItem.Episodes(), BottomBarItem.Characters())
Scaffold(bottomBar = {
BottomNavigation {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
items.forEach { item ->
BottomNavigationItem(icon = { item.icon },
label = { Text(item.title) },
selected = currentDestination?.hierarchy?.any { it.route == item.route } == true,
onClick = {
navController.navigate(item.route) {
navController.graph.startDestinationRoute?.let { route ->
popUpTo(route) {
saveState = true
}
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
})
}
}
}) {
Box(
modifier = Modifier.padding(it)
) {
Image(
painter = painterResource(Res.drawable.space),
contentDescription = "background",
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop
)
NavigationBottom(navController, mainNavController)
}
}
The navigation works fine, and I now every navigation to CharacterScreen is the same instance because I have a log on my ViewModel to verify I not create a new instance of this.
class CharactersViewModel(val getRandomCharacter: GetRandomCharacter, repository: Repository) : ViewModel() {
private val _state = MutableStateFlow(CharactersState())
val state: StateFlow<CharactersState> = _state
val characters: Flow<PagingData<CharacterModel>> = repository.getAllCharacters()
init {
Napier.i { "Created" }
viewModelScope.launch {
val character = withContext(Dispatchers.IO) {
getRandomCharacter()
}
_state.update { it.copy(randomCharacter = character) }
}
}
}
data class CharactersState(
val randomCharacter: CharacterModel? = null
)
The problem is the screen, Its keep the content but ignore the scroll remember so every time I return to Screen the list is on position 0.
fun CharactersScreen(navigateToCharacterDetail: (Int) -> Unit) {
val charactersViewModel = koinViewModel<CharactersViewModel>()
val state = charactersViewModel.state.collectAsState()
val characters = charactersViewModel.characters.collectAsLazyPagingItems()
val lazyGridState = rememberLazyGridState()
LazyVerticalGrid(
modifier = Modifier.fillMaxSize().padding(start = 16.dp, end = 16.dp),
columns = GridCells.Fixed(2),
state = lazyGridState,
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
item(span = { GridItemSpan(2) }) {
Column {
Text(
"Characters",
color = Color.White,
fontSize = 24.sp,
modifier = Modifier.padding(vertical = 8.dp)
)
RandomCharacter(character = state.value.randomCharacter)
}
}
when {
//Carga inicial
characters.loadState.refresh is LoadState.Loading && characters.itemCount == 0 -> {
item (span = { GridItemSpan(2) }){
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
CircularProgressIndicator(
modifier = Modifier.size(64.dp), color = Color.Red
)
}
}
}
//Estado vacio
characters.loadState.refresh is LoadState.NotLoading && characters.itemCount == 0 -> {
item {
Text(text = "Todavía no hay personajes")
}
}
else -> {
items(characters.itemCount, span = { GridItemSpan(1) }) {
characters[it]?.let { characterModel ->
ItemList(characterModel) { navigateToCharacterDetail(it) }
}
}
if (characters.loadState.append is LoadState.Loading) {
item {
Box(
modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center
) {
CircularProgressIndicator(
modifier = Modifier.size(64.dp), color = Color.White
)
}
}
}
}
}
}
}
I thought it was because of the paging but I tried with a simple list and still have the same error.
I tried to create a custom saver, use different remembers and still have the same problem.