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

Navigation Compose类型安全导航报错:找不到Companion类序列化器

问题:Navigation 2.8.0-beta02类型安全API序列化异常

使用Navigation 2.8.0-beta02内置的类型安全API为Compose导航图提供编译时安全保障,已配置Kotlin序列化插件及依赖,但运行时抛出以下异常:

kotlinx.serialization.SerializationException: Serializer for class 'Companion' is not found.
Please ensure that class is marked as '@Serializable' and that the serialization compiler plugin is applied.
原因分析

异常根源在于代码中直接将Home类本身传递给了startDestination和popUpTo方法,而非Home类的实例。Navigation的类型安全API需要序列化目的地实例,传递类本身时,系统会尝试序列化该类的Companion对象,但这个Companion并未被标记为@Serializable,从而触发序列化失败。

解决方案

步骤1:为Home类添加默认实例

在Home类中定义一个无参的默认实例,作为起始目的地的标识:

@Serializable
data class Home(
    val action: String = "" // 设置默认值,允许无参构造
) {
    // 定义单例作为起始目的地的固定标识
    companion object {
        val Default = Home("")
    }
}

步骤2:修改起始目的地为实例

将NavHost的startDestination改为Home的实例:

NavHost(
    navController = navController,
    startDestination = Home.Default // 或者直接使用Home("")
) {
    addHomeScreen(
        navigateToTaskScreen = screens.detail
    )    
}

步骤3:修改popUpTo参数为实例

在Screens类的home方法中,将popUpTo的参数改为Home的实例:

val home: (Action) -> Unit = {
    navController.navigate(Home(it.name)) {
        popUpTo(Home.Default) { inclusive = true } // 使用实例而非类本身
    }
}
修改后的完整导航代码示例
@Composable
fun SetupNavigation(
    navController: NavHostController
) {
    val screens = remember(navController) {
        Screens(navController = navController)
    }

    NavHost(
        navController = navController,
        startDestination = Home.Default
    ) {
        addHomeScreen(
            navigateToTaskScreen = screens.detail
        )    
    }
}

@Serializable
data class Home(
    val action: String = ""
) {
    companion object {
        val Default = Home("")
    }
}

@Serializable
data class Details(
    val id: Int
)

fun NavGraphBuilder.addHomeScreen(
    navigateToTaskScreen: (Int) -> Unit
){
    composable<Home>{
        HomeScreen(navigateToTaskScreen = navigateToTaskScreen)
    }

}

class Screens(
    navController: NavHostController
) {
    val home: (Action) -> Unit = {
        navController.navigate(Home(it.name)) {
            popUpTo(Home.Default) { inclusive = true }
        }
    }

    val detail: (Int) -> Unit = {
        navController.navigate(Details(it))
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 19:08:11