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

Compose NavHost实现类型安全导航遇类型不匹配错误

问题:Navigation Compose传递对象时出现类型不匹配错误

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)
        // ...
}
fun NavController.navigateToTodays(topicId: ItemUI? = null, navOptions: NavOptions? = null) {
    navigate(topicId, navOptions)
}

问题原因与解决方案

核心原因

  1. navigateToTodays的topicId参数是可空类型ItemUI?,但上游forYouScreen的onTopicClick回调要求传入非空ItemUI,同时Navigation类型安全导航默认不接受可空对象参数。
  2. 未给目标页面配置对应的对象类型导航参数,直接调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 03:34:58