迁移至kotlinx.parcelize.Parcelize遇Parceler超类型无法解析问题
迁移kotlinx.parcelize时Parceler超类型解析失败问题排查
问题现象
从kotlinx.android.parcel.Parcelize迁移至kotlinx.parcelize.Parcelize后,出现编译错误:
无法解析com.myapp.models.Text.Raw.Companion的超类型kotlinx.parcelize.Parceler,请确认类路径依赖是否齐全
移除Raw类中的伴生对象后,错误消失。
原代码(旧Parcelize库)
import android.content.Context import android.os.Parcel import android.os.Parcelable import kotlinx.android.parcel.Parceler import kotlinx.android.parcel.Parcelize sealed class Text : Parcelable { @Parcelize data class Raw(private val text: CharSequence) : Text() { override fun resolveToCharSequence(context: Context): CharSequence = text companion object : Parceler<Raw> { override fun create(parcel: Parcel): Raw { return Raw(checkNotNull(parcel.readString())) } override fun Raw.write(parcel: Parcel, flags: Int) { parcel.writeString(text.toString()) } } } ... }
修改后代码(新版Parcelize库,仍报错)
import android.content.Context import android.os.Parcel import android.os.Parcelable import kotlinx.parcelize.Parceler import kotlinx.parcelize.Parcelize sealed class Text : Parcelable { @Parcelize data class Raw(private val text: CharSequence) : Text() { override fun resolveToCharSequence(context: Context): CharSequence = text companion object : Parceler<Raw> { override fun create(parcel: Parcel): Raw { return Raw(checkNotNull(parcel.readString())) } override fun Raw.write(parcel: Parcel, flags: Int) { parcel.writeString(text.toString()) } } } ... }
项目配置(build.gradle.kts)
plugins { com.android.library `kotlin-android` `kotlin-parcelize` `kotlin-kapt` } ...
问题原因
新旧版本的Parcelize库对自定义序列化逻辑的实现规范完全不同:
- 旧版
kotlinx.android.parcel允许通过让类的伴生对象直接实现Parceler接口来定义自定义序列化逻辑; - 新版
kotlinx.parcelize已废弃这种写法,Parceler接口的使用方式改为独立类实现+通过@Parcelize注解参数指定,或使用函数式的parcelableCreator方法生成CREATOR。直接让伴生对象实现Parceler会导致插件无法正确解析接口继承关系,从而抛出类路径错误。
解决方法
适配新版kotlinx.parcelize的规范,修改自定义序列化逻辑的写法,以下两种方式任选其一:
方式一:独立Parceler类+注解参数指定
import android.content.Context import android.os.Parcel import android.os.Parcelable import kotlinx.parcelize.Parceler import kotlinx.parcelize.Parcelize sealed class Text : Parcelable { @Parcelize(parceler = RawParceler::class) data class Raw(private val text: CharSequence) : Text() { override fun resolveToCharSequence(context: Context): CharSequence = text } // 独立实现Parceler接口 object RawParceler : Parceler<Raw> { override fun create(parcel: Parcel): Raw { return Raw(checkNotNull(parcel.readString())) } override fun Raw.write(parcel: Parcel, flags: Int) { parcel.writeString(text.toString()) } } ... }
方式二:函数式CREATOR写法(推荐)
import android.content.Context import android.os.Parcel import android.os.Parcelable import kotlinx.parcelize.Parcelize import kotlinx.parcelize.parcelableCreator sealed class Text : Parcelable { @Parcelize data class Raw(private val text: CharSequence) : Text() { override fun resolveToCharSequence(context: Context): CharSequence = text companion object { @JvmField val CREATOR = parcelableCreator<Raw> { parcel -> Raw(checkNotNull(parcel.readString())) } } } ... }
额外注意:确保kotlin-parcelize插件版本与项目中Kotlin版本保持一致,避免版本不兼容引发的依赖问题。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

