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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:31:20