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

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

解决Jetpack Compose Navigation 2.8.0传递自定义Parcelable对象的问题

Jetpack Compose Navigation 2.8.0支持用@Serializable数据类实现类型安全路由,但默认无法处理路由类中包含自定义Parcelable对象的场景。比如你定义的密封路由类:

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

其中UserData是@Parcelize标记的自定义Parcelable类,下面提供两种可行的解决方案:


方案一:自定义NavType + NavTypeSerializer(推荐,保留Parcelable传递特性)

1. 实现自定义NavType

创建处理UserData的NavType子类,负责Bundle中Parcelable对象的读写和字符串解析(支持Deep Link):

class UserDataNavType : NavType<UserData>(isNullableAllowed = false) {
    override fun get(bundle: Bundle, key: String): UserData? {
        return bundle.getParcelable(key)
    }

    override fun parseValue(value: String): UserData {
        // 从Base64字符串解析为Parcelable
        val bytes = Base64.decode(value, Base64.DEFAULT)
        val parcel = Parcel.obtain()
        parcel.unmarshall(bytes, 0, bytes.size)
        parcel.setDataPosition(0)
        val userData = UserData.CREATOR.createFromParcel(parcel)
        parcel.recycle()
        return userData
    }

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

    override val name: String
        get() = "UserData"
}

2. 注册NavTypeSerializer

创建NavTypeSerializer实例,将UserData类型与自定义NavType绑定:

@NavTypeSerializer
object UserDataNavTypeSerializer : NavTypeSerializer<UserData> {
    override val navType: NavType<UserData> = UserDataNavType()
}

3. 使用类型安全路由

直接在导航图中使用类型安全的路由定义,跳转时传递完整的Route对象即可:

// 导航图定义
NavHost(navController = navController, startDestination = ...) {
    composable<Route.DetailsScreen> { backStackEntry ->
        val route = backStackEntry.toRoute<Route.DetailsScreen>()
        DetailsScreen(route.userData)
    }
}

// 跳转调用
navController.navigate(Route.DetailsScreen(userData))

方案二:给Parcelable添加Kotlinx Serialization序列化器

通过将Parcelable对象序列化为Base64字符串,让导航组件以字符串形式传递数据:

1. 给UserData添加自定义序列化器

@Parcelize
@Serializable(with = UserDataSerializer::class)
data class UserData(val id: String, val name: String) : Parcelable

2. 实现Kotlinx Serialization序列化器

object UserDataSerializer : KSerializer<UserData> {
    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UserData", PrimitiveKind.STRING)

    override fun serialize(encoder: Encoder, value: UserData) {
        // 将Parcelable转为Base64字符串
        val parcel = Parcel.obtain()
        value.writeToParcel(parcel, 0)
        val bytes = parcel.marshall()
        parcel.recycle()
        encoder.encodeString(Base64.encodeToString(bytes, Base64.DEFAULT))
    }

    override fun deserialize(decoder: Decoder): UserData {
        // 将Base64字符串转回Parcelable
        val bytes = Base64.decode(decoder.decodeString(), Base64.DEFAULT)
        val parcel = Parcel.obtain()
        parcel.unmarshall(bytes, 0, bytes.size)
        parcel.setDataPosition(0)
        val userData = UserData.CREATOR.createFromParcel(parcel)
        parcel.recycle()
        return userData
    }
}

3. 直接使用类型安全路由

完成序列化器定义后,无需额外配置,直接使用类型安全的导航API即可,导航组件会自动处理UserData的序列化与反序列化。


内容的提问来源于stack exchange,提问作者Michael B

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 00:04:53