Android Compose导航传递对象失败:共享ViewModel取值为null
问题原因与解决方案
核心问题:ViewModel实例不共享
你遇到的问题根源是列表页和详情页拿到的是两个不同的ViewModel实例。默认情况下,hiltViewModel()会以当前导航目的地的ViewModelStoreOwner作为作用域,每个导航页面都有独立的ViewModel存储容器,所以详情页的ViewModel里campaign还是初始的null值,和列表页的ViewModel完全无关。
解决方法:指定共享ViewModel的作用域
要实现跨页面共享ViewModel,需要将ViewModel的作用域指定为包含列表页和详情页的父导航图,这样两个页面都会获取到同一个ViewModel实例。
代码修正示例
1. 列表页获取共享ViewModel
// 列表页中 val navController = rememberNavController() // 替换"parent_campaign_graph"为你的父导航图route val sharedViewModel = hiltViewModel<YourCampaignViewModel>( navBackStackEntry = remember { navController.getBackStackEntry("parent_campaign_graph") } ) // 点击CampaignItem时调用 sharedViewModel.addCampaign(selectedCampaign) navController.navigate("campaign_detail_screen")
2. 详情页获取同一个共享ViewModel
// 详情页中 val navController = rememberNavController() val sharedViewModel = hiltViewModel<YourCampaignViewModel>( navBackStackEntry = remember { navController.getBackStackEntry("parent_campaign_graph") } ) val campaign by sharedViewModel.campaign Timber.v("CampaignDetailsScreen2: $campaign")
注意:确保parent_campaign_graph是你导航图中包含列表页和详情页的父级导航节点的route。
MutableState核心原理说明
mutableStateOf是Compose提供的可观察状态容器,核心特性如下:
- 它是
State接口的可变实现,内部会跟踪所有读取其value的Compose函数 - 当
value被修改时,会自动触发所有依赖它的Compose函数进行重组,更新UI - 状态必须被保存在ViewModel、
remember或其他跨重组的容器中,否则会在Compose重组时丢失数据 val campaign by remember { viewModel.campaign }中的remember用于在Compose重组之间保留对State引用的持有,by关键字会自动解包State的value属性
但前提是ViewModel本身是同一个实例,否则即使State的逻辑正确,也无法共享状态。
内容的提问来源于stack exchange,提问作者Ahmed Rabee
相关产品推荐
相关产品推荐

