Reputation: 24583
I am trying to show a walkthrough of my app on initial start up. I am trying to present 3 screens
Welcome Screen1 Screen2
I have this navigation graph
composable(Routes.Welcome.name) {
WelcomeScreen(
done = {
navController.navigate(Routes.Screen1.name)
}
)
}
composable(Routes.Screen1.name) {
Screen1(
done = {
navController.navigate(Routes.Screen2.name) {
popUpTo(Routes.Welcome.name)
}
}
)
}
composable(Routes.Screen2.name) {
Screen2(
done = {
navController.navigate(Routes.Screen3.name) {
popUpTo(Routes.Welcome.name)
}
}
)
}
composable(Routes.Screen3.name) {
Screen1(
done = {
navController.navigate(Routes.Main.name)
}
)
}
However when I am done with Screen1 and I try to navigate to Screen2 I end up in an infinite loop with Screen1 done continuously being called while Screen2 is presented.
@Composable
fun Screen1(
done: () -> Unit,
viewModel: StartupViewModel = hiltViewModel()
) {
val screen1 by viewModel.screen1.observeAsState()
if (screen1 != true) {
Button(onClick = { viewModel.setScreen1(true) }) {
Text(text = "Go to screen 2")
}
} else {
// once screen1 is set in viewmodel I should end up here.
// let my parent handle navigation to next screen.
done()
}
}
Upvotes: 4
Views: 1305
Reputation: 6207
It looks like a similar issue like this and this.
Based on the official Docs,
You should only call navigate() as part of a callback and not as part of your composable itself, to avoid calling navigate() on every recomposition.
The culprit is in the entire if-else
block.
val screen1 by viewModel.screen1.observeAsState()
if (screen1 != true) {
...
} else {
...
done()
}
At first pass of composition, the if{…}
block will execute, but when you update the screen1
state it will satisfy the else{…}
block calling your navigation, it will then call a re-composition
of the NavHost
which in turn call this composable again and because screen1 != true
stills evaluate to false
it will call the else{…}
block again, now your navigation is on a vicious loop.
I would suggest doing this inside a LaunchedEffect
.
Please check this, the code in question looks closely similar to yours.
Upvotes: 1