Jetpack Compose导航:通过SavedStateHandle向起始目标ViewModel传参
多Activity架构下导航起始目标ViewModel的参数传递方案
针对你遇到的问题,这里提供两种无需大幅改动现有架构的解决方案,核心都是让Intent中的参数能被ViewModel的SavedStateHandle正确获取:
方案一:将参数拼入起始导航路由(推荐)
这种方式完全贴合导航组件的原生参数传递逻辑,和你在单导航图内的传参方式保持一致,无需修改ViewModel代码。
修改FooActivity的代码,把从Intent拿到的参数直接拼入startDestination的路由字符串中:
@AndroidEntryPoint class FooActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 处理参数非空情况,根据业务需求调整默认值或异常抛出逻辑 val param = intent?.getStringExtra("foo-param") ?: "default-value" setContent { AppTheme { val navController = rememberNavController() NavHost( navController = navController, // 将实际参数拼入起始路由,替换占位符 startDestination = "foo-route/$param", ) { composable( route = "foo-route/{foo-param}", arguments = listOf( navArgument("foo-param") { type = NavType.StringType }, ), ) { FooScreen(viewModel = hiltViewModel()) } } } } } }
导航组件会自动解析路由中的参数,并将其存入对应导航目标的SavedStateHandle,你的FooViewModel无需任何改动就能正常获取到foo-param。
方案二:手动注入参数到BackStackEntry的SavedStateHandle
如果不想修改起始路由的格式,可以在导航目标的Composable中,手动将Intent参数存入当前BackStackEntry的SavedStateHandle,再初始化ViewModel:
@AndroidEntryPoint class FooActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val param = intent?.getStringExtra("foo-param") setContent { AppTheme { val navController = rememberNavController() NavHost( navController = navController, startDestination = "foo-route/{foo-param}", ) { composable( route = "foo-route/{foo-param}", arguments = listOf( navArgument("foo-param") { type = NavType.StringType }, ), ) { backStackEntry -> param?.let { // 将参数手动存入当前导航栈条目SavedStateHandle backStackEntry.savedStateHandle["foo-param"] = it } FooScreen(viewModel = hiltViewModel(backStackEntry = backStackEntry)) } } } } } }
这种方式同样能让FooViewModel通过SavedStateHandle获取到参数,适合需要保留路由占位符格式的场景。
内容的提问来源于stack exchange,提问作者Fried Rice
相关产品推荐
相关产品推荐

