为什么当我返回时 LaunchedEffect 会第二次调用?

Max*_*tin 16 android android-jetpack-compose

我想显示一些数据并模拟加载。因此,我在第一个屏幕上使用 LaunchedEffect。它工作正常,但是当我添加导航时, LaunchedEffect 启动两次。

导航:第一个 (LaunchedEffect) -> 第二个 -> 返回第一个(LaunchedEffect 再次启动)

我希望当我返回第一个屏幕时 LaunchedEffect 将不会启动,我将立即看到数据。

启动效果示例:

@Composable
fun FirstScreen(...) {
    ...
    LaunchedEffect(Unit) {
        state = State.Loading
        delay(2_000L)
        state = State.Success(...)
    }
}
Run Code Online (Sandbox Code Playgroud)

导航示例:

val navController = rememberNavController()
NavHost(
    navController = navController,
    startDestination = FIRST_ROTE
) {
    composable(FIRST_ROTE) { FirstScreen(...) }
    composable(SECOND_ROTE) { SecondScreen(...) }
}
Run Code Online (Sandbox Code Playgroud)

ngl*_*ber 11

看看文档怎么说

要从可组合项内部安全地调用挂起函数,请使用 LaunchedEffect可组合项。当LaunchedEffect进入组合时,它会启动一个协程,并将代码块作为参数传递。LaunchedEffect如果离开组合,协程将被取消。如果LaunchedEffect用不同的键重组,现有的协程将被取消,新的挂起功能将在新的协程中启动。

当您导航到另一个屏幕时,可组合项将从合成中删除(这意味着它不会被绘制)。这就是再次执行的原因LaunchedEffect

您可以使用视图模型中的状态来控制此执行。就像是:

@Composable
fun FirstScreen(vm: YourViewModel) {
    LaunchedEffect(Unit) {
        if (vm.someFlag == true) {
            vm.someFlag = false
            state = State.Loading
            delay(2_000L)
            state = State.Success(...)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @levi因为它不是重新组合而是再次组合。屏幕 1 出现,效果启动,屏幕 2 出现,屏幕 1 离开合成树,我们回到屏幕 1,屏幕 1 已合成而不是重新合成,因此效果已启动。 (4认同)
  • 有更好的方法吗? (2认同)