Navigation Compose类型安全导航报错:找不到Companion类序列化器
使用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
相关产品推荐
相关产品推荐

