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,避免层层传参的繁琐:
- 先定义一个CompositionLocal:
val LocalMainViewModel = staticCompositionLocalOf<MainViewModel> { error("MainViewModel未在根Composable中提供") }
- 在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
相关产品推荐
相关产品推荐

