Compose NavHost传参至Dagger-Hilt ViewModel空值崩溃问题排查
问题分析与解决方法
核心错误点
你的代码存在三个关键问题,导致argument为空并崩溃:
1. 路由定义缺少参数占位符
ScreenRoutes.AstronautDetailsScreen.route未包含{astronautId}占位符,导航时参数无法被NavHost捕获并传入SavedStateHandle。
修正方式:
修改路由定义,添加参数占位符:
object ScreenRoutes { const val AstronautDetailsScreen = "astronaut_details/{astronautId}" }
2. 跳转页面时未携带参数
跳转到目标页面时,必须在路由后拼接实际的astronautId值,否则参数不会被传递。
修正方式:
跳转代码示例:
navController.navigate(ScreenRoutes.AstronautDetailsScreen.replace("{astronautId}", astronautId.toString()))
或直接拼接:
navController.navigate("astronaut_details/$astronautId")
3. ViewModel注入方式错误
你在NavHost中直接传递astronautDetailsViewModel实例,Hilt无法将当前BackStackEntry的SavedStateHandle关联到该ViewModel,导致ViewModel拿不到参数。
修正方式:
在AstronautDetailScreen内部使用hiltViewModel()获取ViewModel,而非外部传入:
@Composable fun AstronautDetailScreen() { val viewModel: AstronautDetailsViewModel = hiltViewModel() val astronautDetails by viewModel.astronautDetails.observeAsState(AstronautDetails()) // 其他UI逻辑 }
同时简化NavHost中的代码:
composable( ScreenRoutes.AstronautDetailsScreen.route, arguments = listOf(navArgument("astronautId") { type = NavType.IntType }) ) { AstronautDetailScreen() }
额外验证点
- 确认
navArgument的名称"astronautId"与ViewModel中savedStateHandle.get的名称完全一致,包括大小写。
内容的提问来源于stack exchange,提问作者juske
相关产品推荐
相关产品推荐

