Kotlin data object反Parcel时字节数不匹配问题求助
解决Kotlin data object反Parcel时字节数不匹配的WTF日志问题
检查Parcelable实现的一致性
如果使用@Parcelize注解自动生成Parcelable代码,确认所有属性都被正确标记参与序列化(避免用@IgnoredOnParcel遗漏必要属性)。如果是手动实现writeToParcel和createFromParcel,必须保证读写的顺序、类型、数量完全一致:- 写入时用
writeInt(placeholder),读取时必须先执行readInt(),不能颠倒顺序; - 集合类型如
List,写入用writeTypedList(attachments),读取必须用createTypedArrayList(MyAttachment.CREATOR),禁止混用writeList和createArrayList这类不匹配的方法。
- 写入时用
排查data object单例特性的冲突
Kotlin的data object是单例,而Parcelable默认逻辑是序列化对象状态、反序列化生成新实例,二者存在天然冲突:- 若用
@Parcelize生成代码,反序列化时可能仍尝试创建新实例,但data object不允许实例化新对象,会导致内部逻辑混乱; - 手动实现时,
createFromParcel应直接返回单例实例(比如MyClass.INSTANCE),但如果writeToParcel中仍写入了属性数据,就会出现“写入字节但读取时未消耗”的不匹配。此时需修改writeToParcel为空实现,因为单例无需序列化状态。
- 若用
清理Parcel复用或状态污染问题
严格规范Parcel对象的使用流程:- 每次序列化/反序列化优先使用新的Parcel实例,复用前必须调用
recycle()重置状态; - 写入完成后,必须调用
setDataPosition(0)将指针移到起始位置再开始读取,否则会从中间位置读取,导致字节数计算错误。重启后数值变化大概率和Parcel内存缓存、初始分配的块大小有关,规范使用可消除这类随机偏差。
- 每次序列化/反序列化优先使用新的Parcel实例,复用前必须调用
验证序列化字节数的准确性
手动计算写入的总字节数,和Parcel的dataSize()对比:- 基础类型:int占4字节,long占8字节,String的字节数为
string.toByteArray(Charsets.UTF_8).size + 4(含前缀长度); - 嵌套Parcelable:会先写入4字节的长度前缀,再写入对象数据;
如果自动生成代码存在问题,执行./gradlew clean清理构建缓存,重新生成Parcelable实现,避免旧代码残留导致的逻辑错误。
- 基础类型:int占4字节,long占8字节,String的字节数为
排查嵌套对象的Parcel实现
如果data object包含嵌套的自定义Parcelable(比如attachments里的元素),必须确保这些嵌套类的Parcel实现完全正确:- 检查嵌套类是否遗漏属性读写,或读写顺序错误;
- 可变集合要保证写入时的状态和读取时的预期一致,避免写入后集合被修改导致序列化数据和实际读取的字节数不匹配。
内容的提问来源于stack exchange,提问作者WhatTheClown
相关产品推荐
相关产品推荐

