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

Jetpack Compose Navigation传递带伴生对象的数据类参数报错问题

结论

直接通过savedStateHandle传递未做序列化处理的自定义数据类实例的方式不可行,你遇到的伴生对象类型不支持报错,本质是框架对存入参数的类型校验机制触发的,不存在专门的标记可以让框架直接忽略伴生对象,但是可以通过正确实现序列化的方式绕开这个问题,不需要改动伴生对象本身的代码。

报错核心原因

savedStateHandle底层基于Bundle实现存储,仅原生支持基础数据类型、字符串等系统默认可序列化类型,对于自定义类型,会递归校验其所有关联结构是否符合序列化要求。你传入的数据类没有实现合法的序列化接口时,框架扫描类结构时会识别到内部的伴生对象,而伴生对象是类级单例,不满足Bundle存储的类型要求,就会抛出你看到的异常:

java.lang.IllegalArgumentException: Object of type blablabla$Companion is not supported for navigation arguments.

可行实现方案(不使用共享ViewModel)
  • 方案1:给数据类添加@Parcelize注解实现Parcelable接口
    Kotlin提供的@Parcelize注解会自动生成数据类主构造函数内声明字段的序列化逻辑,默认不会处理类内部的伴生对象,伴生对象里定义的常量、方法都不会被纳入序列化传递的范围,完全符合你不需要传递伴生对象内容的需求。代码示例:
    import android.os.Parcelable
    import kotlinx.parcelize.Parcelize
    
    @Parcelize
    data class YourBizData(
        val itemId: Long,
        val title: String,
        val content: String
        // 仅在此处声明需要传递的业务字段
    ) : Parcelable {
        companion object {
            // 伴生对象内的代码不需要做任何修改,不会被序列化逻辑扫描
            const val TYPE_NORMAL = 1
            fun createEmpty() = YourBizData(0, "", "")
        }
    }
    
    实现完Parcelable接口后,你原来的传参代码navController.currentBackStackEntry?.savedStateHandle?.set("arg", item)不需要修改,即可正常存入和读取数据类实例。
  • 方案2:将数据类序列化为JSON字符串传递
    如果你不想给数据类实现Parcelable接口,可以先把数据类实例转成JSON格式的字符串,再通过savedStateHandle存储——字符串是原生支持的存储类型,不会触发自定义类型校验,接收端拿到字符串后再反序列化为对应数据类即可。这种方式全程不会扫描类的伴生对象结构,不会触发对应异常。
补充说明

没有办法实现“连带伴生对象一同传递”的效果:伴生对象是类绑定的全局单例,不属于数据类实例的成员字段,本身不存在序列化存储的可能性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 05:30:47