Kotlin中Parcelize与ObjectBox冲突:实体属性序列化丢失如何解决?
解决ObjectBox实体类使用@Parcelize时关联字段被忽略的问题
这个问题我之前在项目里也碰到过,ObjectBox的ToOne和@Backlink修饰的列表确实和Kotlin的@Parcelize有点“水土不服”——默认情况下这些关联字段会被序列化忽略,而且@Parcelize还不让我们直接重写writeToParcel方法。不过别担心,有个官方推荐的靠谱解法:自定义Parceler,下面我给你一步步讲清楚怎么实现。
核心思路
@Parcelize允许我们通过parceler参数指定自定义的序列化/反序列化逻辑,不用去重写系统的writeToParcel和createFromParcel方法。我们只需要为每个实体类实现一个Parceler,手动处理ToOne和@Backlink字段的序列化即可。
具体实现步骤
1. 为Order类实现自定义Parceler
Order里的customer是ToOne<Customer>类型,序列化时我们需要把它关联的Customer实体写入Parcel,反序列化时再把读取到的Customer设置回ToOne的target属性:
object OrderParceler : Parceler<Order> { override fun create(parcel: Parcel): Order { val order = Order() // 读取基础字段 order.id = parcel.readLong() // 读取关联的Customer并设置到ToOne val customer = parcel.readParcelable<Customer>(Customer::class.java.classLoader) customer?.let { order.customer.target = it } return order } override fun Order.write(parcel: Parcel, flags: Int) { // 写入基础字段 parcel.writeLong(id) // 写入ToOne关联的Customer实体 parcel.writeParcelable(customer.target, flags) } }
2. 为Customer类实现自定义Parceler
Customer里的orders是@Backlink修饰的列表,它本质是ObjectBox的懒加载列表,所以序列化时要先转成普通List;反序列化时要把每个Order的customer.target指向当前Customer,重建关联关系:
object CustomerParceler : Parceler<Customer> { override fun create(parcel: Parcel): Customer { val customer = Customer() // 读取基础字段 customer.id = parcel.readLong() // 读取orders列表并重建关联 val orders = parcel.createTypedArrayList(Order.CREATOR) ?: emptyList() customer.orders = orders.map { it.customer.target = customer it } return customer } override fun Customer.write(parcel: Parcel, flags: Int) { // 写入基础字段 parcel.writeLong(id) // 把懒加载列表转成普通List后写入 parcel.writeTypedList(orders.toList()) } }
3. 给实体类添加@Parcelize并指定Parceler
最后修改你的实体类,加上@Parcelize注解并指定我们刚才写的Parceler:
@Entity @Parcelize(parceler = OrderParceler::class) class Order : Parcelable { @Id var id: Long = 0 lateinit var customer: ToOne<Customer> } @Entity @Parcelize(parceler = CustomerParceler::class) class Customer : Parcelable { @Id var id: Long = 0 @Backlink lateinit var orders: List<Order> }
注意事项
- 确保关联的实体类(比如这里的
Customer和Order)都实现了Parcelable接口,不然序列化时会抛出异常。 @Backlink修饰的列表是ObjectBox的LazyList,一定要用toList()转成普通List再序列化,避免懒加载导致的序列化失败。- 反序列化时记得重建实体间的关联关系,这样ObjectBox的关系查询才能正常工作。
这个方法完全符合@Parcelize的设计规范,而且能完美解决关联字段被忽略的问题,我在项目里用了挺久的,没出过问题~
内容的提问来源于stack exchange,提问作者Sriram R
相关产品推荐
相关产品推荐

