在Jetpack Compose的类型安全导航(Navigation 2.8.0及以上)中,如何传递自定义Parcelable对象?

移动开发 2026-07-09

随着Jetpack Compose Navigation 2.8.0的发布,我们现在可以使用类型安全的对象(@Serializable 数据类)来进行导航,而不是路由字符串。

然而,如果我的路由数据类包含一个自定义的 Parcelable 对象,导航组件默认并不知道如何处理它。

例如,我为我的路由定义了一个密封类:

@Serializable
    sealed class Route {
        @Serializable
        data class DetailsScreen(val userData: UserData) : Route()
    }

其中 UserData 是一个 @Parcelize 类。如何为这个 Parcelable 对象定义并注册一个自定义的 NavType,以便在新的Compose导航图中安全地传递它?

解决方案

新的类型安全导航(2.8.0)很不错,但它原生并不能直接处理 Parcelable 对象,这有点让人恼火。你必须手动定义一个自定义的 NavType,因为库不知道如何将你的自定义类序列化成路由字符串。

下面是使用 kotlinx.serialization 的最简洁方法。

首先为你的对象创建一个Nav类型。

使用这个通用辅助工具来处理JSON的编码和解码。 例如

val UserDataNavType = object : NavType<UserData>(isNullableAllowed = false) {
    override fun get(bundle: Bundle, key: String): UserData? {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            bundle.getParcelable(key, UserData::class.java)
        } else {
            @Suppress("DEPRECATION")
            bundle.getParcelable(key)
        }
    }

    override fun parseValue(value: String): UserData {
        return Json.decodeFromString(value)
    }

    override fun put(bundle: Bundle, key: String, value: UserData) {
        bundle.putParcelable(key, value)
    }

    override fun serializeAsValue(value: UserData): String {
        return Uri.encode(Json.encodeToString(value))
    }
}

现在把它传给你的Nav控制器

在定义你的 composable 目标时,必须在 typeMap 注册这个类型。

composable<Route.Details>(
    typeMap = mapOf(typeOf<UserData>() to UserDataNavType)
) { backStackEntry ->
    val details = backStackEntry.toRoute<Route.Details>()
    DetailScreen(details.userData)
}

现在你可以在Navigate中正常传递对象。

navController.navigate(Route.Details(myUserObject))

重要! 确保 UserData 类同时被 @Parcelize@Serializable 这两个注解标注。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章