You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Navigation中从A到B再返回时如何保留Screen A的状态?

Android Navigation Compose 状态丢失问题解决

问题根源

你遇到的状态丢失问题,核心原因是每次从Screen B返回Screen A时,ScreenViewModel被重新创建了。

在你的导航图代码中,composable的lambda块会在Screen A每次进入(包括从回栈恢复)时重新执行,而你在这里直接通过val viewModel = ScreenViewModel()创建实例,导致每次都生成全新的ViewModel,之前的计数器状态自然无法保留。即使Screen A在导航回栈中,Composable的重组机制也会重新执行这段代码,生成新的ViewModel实例。

解决方案

要让ViewModel与导航目的地的生命周期绑定,确保回栈中的页面保留状态,有两种常用方式:

方案1:使用viewModel()函数(推荐)

使用Jetpack Compose提供的viewModel()函数获取ViewModel,它会自动将ViewModel与当前导航目的地的BackStackEntry绑定,只要目的地在回栈中,ViewModel就不会被销毁。

修改导航图代码:

fun Navigation(navController: NavHostController) {
    NavHost(navController = navController, startDestination = Screens.Screen1.title) {
        composable(route = Screens.Screen1.title) {
            // 使用viewModel()函数获取实例,而非直接new
            val viewModel: ScreenViewModel = viewModel()
            Screen1(viewModel, count = viewModel.count.collectAsState())
        }
        composable(route = Screens.Screen2.title) {
            Screen2(
                onButtonClick = { navController.navigateUp() }
            )
        }
    }
}

方案2:手动绑定BackStackEntry

如果需要更自定义的ViewModel创建逻辑,可以直接使用BackStackEntry作为ViewModelStoreOwner,通过ViewModelProvider创建实例,并用remember确保实例不会重复创建:

fun Navigation(navController: NavHostController) {
    NavHost(navController = navController, startDestination = Screens.Screen1.title) {
        composable(route = Screens.Screen1.title) { backStackEntry ->
            val viewModel = remember(backStackEntry) {
                ViewModelProvider(backStackEntry).get(ScreenViewModel::class.java)
            }
            Screen1(viewModel, count = viewModel.count.collectAsState())
        }
        composable(route = Screens.Screen2.title) {
            Screen2(
                onButtonClick = { navController.navigateUp() }
            )
        }
    }
}

优化建议

你还可以简化Screen1的代码,直接在Composable内部收集状态,避免额外的参数传递:

@Composable
fun Screen1(viewModel: ScreenViewModel = viewModel()) {
    val count by viewModel.count.collectAsState()
    Column {
        Button(onClick = { viewModel.onButtonPressed() }) {
            Text("Counter")
        }
        Text(count.toString())
    }
}

对应的导航图代码可以简化为:

composable(route = Screens.Screen1.title) {
    Screen1()
}

内容的提问来源于stack exchange,提问作者archviz_fan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 22:31:16