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

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实例,数据自然实现共享。

三、验证效果

  1. 在Screen A中选择媒体文件,点击Next按钮调用viewModel.updateSelectedMedia(selectedMediaList)并导航到Screen B
  2. Screen B中通过collectAsStateWithLifecycle()获取到的selectedMediaList应该和Screen A中选择的一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 04:53:22