Compose NavHost实现类型安全导航遇类型不匹配错误
Navigation从2.8.0-alpha08版本开始支持在导航中传递对象,我需要传递ItemUI类型实例而非简单值,参照Now In Android应用的导航风格实现后,在navigate(topicId, navOptions)代码行出现错误:
Type mismatch: inferred type is ItemUI? but TypeVariable(T) was expected
实现代码
ForYouNavigation
fun NavController.navigateToForYou(navOptions: NavOptions) = navigate(FOR_YOU_ROUTE, navOptions) @ExperimentalMaterial3AdaptiveApi fun NavGraphBuilder.forYouScreen(onTopicClick: (ItemUI) -> Unit) { composable( route = FOR_YOU_ROUTE, ) { ForYouRoute(onTopicClick = onTopicClick) } }
NiaNavHost
@Composable fun NiaNavHost( appState: NiaAppState, onShowSnackbar: suspend (String, String?) -> Boolean, modifier: Modifier = Modifier, startDestination: String = FOR_YOU_ROUTE, onReaderClick: () -> Unit ) { val navController = appState.navController NavHost( navController = navController, startDestination = startDestination, modifier = modifier, ) { forYouScreen(onTopicClick = navController::navigateToTodays) // ... }
navigateToTodays
fun NavController.navigateToTodays(topicId: ItemUI? = null, navOptions: NavOptions? = null) { navigate(topicId, navOptions) }
问题原因与解决方案
核心原因
navigateToTodays的topicId参数是可空类型ItemUI?,但上游forYouScreen的onTopicClick回调要求传入非空ItemUI,同时Navigation类型安全导航默认不接受可空对象参数。- 未给目标页面配置对应的对象类型导航参数,直接调用
navigate(obj)重载不符合Navigation的参数传递规范。
解决步骤
1. 统一参数非空性
修改navigateToTodays的参数为非空,匹配上游回调的要求:
fun NavController.navigateToTodays(topicId: ItemUI, navOptions: NavOptions? = null) { navigate(topicId, navOptions) }
2. 配置目标页面的导航参数
假设目标页面路由为TODAYS_ROUTE,需在页面配置中声明对象参数类型(要求ItemUI实现Parcelable或Serializable):
@ExperimentalMaterial3AdaptiveApi fun NavGraphBuilder.todaysScreen() { composable( route = TODAYS_ROUTE, arguments = listOf( navArgument("item_ui") { type = NavType.ParcelableType(ItemUI::class.java) } ) ) { backStackEntry -> val item = backStackEntry.arguments?.getParcelable<ItemUI>("item_ui") TodaysRoute(item = item) } }
3. 正确传递对象参数
修改navigateToTodays,通过Bundle传递对象:
fun NavController.navigateToTodays(topicId: ItemUI, navOptions: NavOptions? = null) { navigate( route = TODAYS_ROUTE, navOptions = navOptions, args = bundleOf("item_ui" to topicId) ) }
4. 让ItemUI实现Parcelable
Navigation传递对象要求对象必须可序列化,推荐实现Parcelable:
@Parcelize data class ItemUI( // 你的字段定义 ) : Parcelable
内容的提问来源于stack exchange,提问作者A. Cedano
相关产品推荐
相关产品推荐

