Compose页面间共享List<String>数据失败,导航报错求助
解决方案
一、修复导航目标找不到的错误
报错信息里的导航URI包含SnapshotStateList(...),说明你之前尝试过通过路由直接传递列表参数(比如注释的MediaList路由),但这种方式不符合Navigation的路由规则,且当前导航图中没有对应的目标。解决步骤:
- 彻底移除所有错误的导航代码(比如注释掉的
navController.navigate(PostRoute.MediaList(selectedMediaList).route)) - 确保导航调用的是正确的、已在导航图中定义的路由:
// Screen A中保留正确的导航代码 viewModel.updateSelectedMedia(selectedMediaList) navController.navigate(PostRoute.Filter.route) - 确认
PostRoute.Filter.route的值($PREFIX/filter)和导航图中注册的路由完全一致,没有拼写错误。
二、实现ViewModel跨页面数据共享
你当前的问题是两个页面的MediaViewModel是独立实例,导致数据无法共享。因为默认hiltViewModel()会为每个Composable创建新的ViewModel,需要将ViewModel的作用域提升到整个Post导航图,让两个页面共享同一个实例:
1. 修改导航图结构,包裹Post路由组
更新postNavGraph.kt,用navigation组件将Post相关路由包裹,创建一个父路由作为ViewModel的作用域:
fun NavGraphBuilder.postNavGraph( navController: NavHostController, ) { // 定义Post导航图的父路由,作为ViewModel的作用域 navigation( startDestination = PostRoute.Create.route, route = "post_root_graph" ) { composable(PostRoute.Create.route) { backStackEntry -> // 从当前导航图获取ViewModel val viewModel = hiltViewModel<MediaViewModel>(backStackEntry) PostCreateScreen(navController, viewModel) } composable(PostRoute.Filter.route) { // 从Post父导航图获取共享的ViewModel val viewModel = hiltViewModel<MediaViewModel>( navController.getBackStackEntry("post_root_graph") ) FilterPostScreen(navController, viewModel) } } }
2. 优化Screen B的代码
Screen B中无需再调用viewModel.updateSelectedMedia(selectedMediaList),这会导致循环更新,直接收集StateFlow数据即可:
// Screen B.kt val selectedMediaList by viewModel.selectedMediaList.collectAsStateWithLifecycle() // 移除多余的LaunchedEffect代码 // LaunchedEffect(selectedMediaList) { // viewModel.updateSelectedMedia(selectedMediaList) // }
3. 确认ViewModel的作用域
@HiltViewModel注解的ViewModel会自动绑定到指定的ViewModelStoreOwner(这里是post_root_graph导航图),因此Screen A和Screen B会使用同一个MediaViewModel实例,数据自然实现共享。
三、验证效果
- 在Screen A中选择媒体文件,点击Next按钮调用
viewModel.updateSelectedMedia(selectedMediaList)并导航到Screen B - Screen B中通过
collectAsStateWithLifecycle()获取到的selectedMediaList应该和Screen A中选择的一致
内容的提问来源于stack exchange,提问作者user2357113
相关产品推荐
相关产品推荐

