Kotlin中如何使用Parcelize实现Any类型List的Parcelable序列化
Kotlin中实现List的Parcelable序列化
@Parcelize注解默认仅支持序列化实现了Parcelable接口的已知类型,由于Any本身没有实现Parcelable序列化规则,编译器无法直接生成List<Any>的序列化逻辑,所以你给出的示例代码直接运行会报错。
可以根据你的业务场景选择以下两种实现方案:
方案一:使用密封类约束元素类型(推荐)
如果List中可能出现的元素类型是可枚举的,优先用密封类代替Any作为List的泛型约束,所有元素类型都实现Parcelable,编译器可以自动生成序列化逻辑,类型安全且无需手动处理序列化细节。
示例代码:
// 定义密封类作为所有列表元素的父类 sealed class ListItem : Parcelable { @Parcelize data class StringItem(val content: String) : ListItem() @Parcelize data class IntItem(val value: Int) : ListItem() @Parcelize data class CustomBeanItem(val bean: CustomBean) : ListItem() } // 自定义业务Bean也实现Parcelable @Parcelize data class CustomBean(val name: String, val age: Int) : Parcelable // 最终传递的数据类 @Parcelize data class Abc( val listOfItem: List<ListItem> ) : Parcelable
方案二:自定义Parceler手动处理序列化逻辑
如果必须保留List<Any>的泛型声明,需要手动实现Parceler接口,通过类型标记区分不同元素类型,自行完成读写逻辑。
示例代码:
import android.os.Parcel import kotlinx.parcelize.Parceler import kotlinx.parcelize.Parcelize @Parcelize data class Abc( val listOfAny: List<Any> ) : Parcelable { companion object : Parceler<Abc> { // 定义支持的元素类型标记 private const val TYPE_STRING = 0 private const val TYPE_INT = 1 private const val TYPE_BOOLEAN = 2 // 可根据业务需求扩展更多支持的类型 override fun Abc.write(parcel: Parcel, flags: Int) { // 先写入列表长度 parcel.writeInt(listOfAny.size) listOfAny.forEach { item -> when (item) { is String -> { parcel.writeInt(TYPE_STRING) parcel.writeString(item) } is Int -> { parcel.writeInt(TYPE_INT) parcel.writeInt(item) } is Boolean -> { parcel.writeInt(TYPE_BOOLEAN) parcel.writeByte(if (item) 1 else 0) } // 新增支持的类型需要在这里补充写入逻辑 else -> throw IllegalArgumentException("不支持的元素类型: ${item::class.java.simpleName}") } } } override fun create(parcel: Parcel): Abc { val listSize = parcel.readInt() val resultList = mutableListOf<Any>() repeat(listSize) { when (val type = parcel.readInt()) { TYPE_STRING -> resultList.add(parcel.readString() ?: "") TYPE_INT -> resultList.add(parcel.readInt()) TYPE_BOOLEAN -> resultList.add(parcel.readByte() == 1.toByte()) // 新增支持的类型需要在这里补充读取逻辑 else -> throw IllegalArgumentException("未知的元素类型标记: $type") } } return Abc(resultList) } } }
注意事项
- 方案二需要提前穷举所有可能出现在List中的元素类型,未被处理的类型会触发异常
- 两种方案都不支持序列化和Android平台组件绑定的类型(如Context、View等),这类对象本身不支持Parcel序列化
内容的提问来源于stack exchange,提问作者Harsh Panchal
相关产品推荐
相关产品推荐

