Jetpack Compose导航无限循环。

4

我正在尝试在应用程序初始启动时展示应用程序操作指南。我试图呈现3个屏幕。

欢迎 屏幕1 屏幕2

我有这个导航图

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)
      }
   )
}

然而,当我完成Screen1并尝试导航到Screen2时,我会陷入一个无限循环中,屏幕1不断被调用,同时屏幕2被呈现。
@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()
   }
}
1个回答

0
看起来这是一个类似于这个这个的问题。
根据官方的文档

为了避免在每次重组时调用navigate(),您应该仅在回调作为一部分而不是作为您自己的合成部分中调用navigate()。

罪魁祸首在整个if-else块中。
val screen1 by viewModel.screen1.observeAsState() 

if (screen1 != true) {
    ...
 } else {
    ...
    done()
}

在合成的第一遍流程中,if{...}块将被执行,但是当您更新screen1状态时,它将满足else{...}块并调用您的导航,然后它将调用NavHostre-composition,进而再次调用此合成体,因为screen1 != true仍然计算结果为false,它将再次调用else{...}块,现在您的导航陷入了一个恶性循环中。
我建议您将其放在LaunchedEffect中处理。
请查看这个链接,其中的代码与您的代码非常相似。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接