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

Compose导航页面获取Activity的ViewModel时hiltViewModel创建新实例问题

获取Compose导航页面中Activity层级的MainViewModel实例

你之前的方案是基于导航图层级共享ViewModel,因此会创建新的实例。要获取Activity层级的ViewModel,需要关联到Activity本身的ViewModelStoreOwner,以下是三种可行的解决方案:

方案一:直接从根Composable传递ViewModel

在Activity的根setContent中获取ViewModel,直接传递给NavHost内的各个页面:

setContent {
    val mainViewModel = viewModel<MainViewModel>()
    NavHost(navController, startDestination = "home") {
        composable(route = "home") {
            HomeScreen(mainViewModel = mainViewModel)
        }
        navigation(startDestination = "myRoute", route = "Parent") {
            composable(route = "myRoute") {
                MyScreen(navController, innerPadding, mainViewModel = mainViewModel)
            }
        }
    }
}

这种方式最直接,确保所有页面拿到的是同一个Activity层级的ViewModel实例。

方案二:使用CompositionLocal全局提供ViewModel

通过CompositionLocal封装ViewModel,避免层层传参的繁琐:

  1. 先定义一个CompositionLocal:
val LocalMainViewModel = staticCompositionLocalOf<MainViewModel> {
    error("MainViewModel未在根Composable中提供")
}
  1. 在Activity的根setContent中提供ViewModel:
setContent {
    val mainViewModel = viewModel<MainViewModel>()
    CompositionLocalProvider(LocalMainViewModel provides mainViewModel) {
        NavHost(navController, startDestination = "home") {
            // ... 其他页面
            navigation(startDestination = "myRoute", route = "Parent") {
                composable(route = "myRoute") {
                    val mainViewModel = LocalMainViewModel.current
                    MyScreen(navController, innerPadding, mainViewModel = mainViewModel)
                }
            }
        }
    }
}

之后任何子Composable都可以通过LocalMainViewModel.current直接获取到同一个实例。

方案三:指定Activity作为ViewModelStoreOwner获取

通过LocalContext获取Activity,将其作为ViewModelStoreOwner传入,直接获取Activity层级的ViewModel:

NavHost(navController, startDestination = "home") {
    // ... 其他页面
    navigation(startDestination = "myRoute", route = "Parent") {
        composable(route = "myRoute") {
            val activity = LocalContext.current as AppCompatActivity
            val mainViewModel = hiltViewModel<MainViewModel>(viewModelStoreOwner = activity)
            MyScreen(navController, innerPadding, mainViewModel = mainViewModel)
        }
    }
}

注意:确保你的Activity继承自AppCompatActivity(或其他实现ViewModelStoreOwner的Activity类),否则强转会失败。

为什么之前的方案会创建新实例?

你之前使用navController.getBackStackEntry("Parent")获取的是导航图层级的ViewModelStoreOwner,hiltViewModel会在这个导航图的ViewModelStore中创建新实例,和Activity层级的ViewModelStore不属于同一个上下文,因此得到的是新对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:13:13