Android:Firestore保存自定义Parcelable类时自动添加stability字段的原因
问题
我定义了一个使用@Parcelize注解的Parcelable数据类Image:
@Parcelize data class Image(val id:String="",val url:String=""):Parcelable
在将数据保存到Firestore时,编写了如下代码:
val data = HashMap<String,Any>() data["title"] = "My Title" data["image"] = Image("dgdg1","https://someimagepath") firestore.collection("collectionname").document(documentId).set(data,SetOptions.merge()).await()
数据已成功保存到Firestore,但image对象中自动添加了额外的stability字段,保存结果如下:
{ "title":"My Title", "image":{ "stability":0, "id":"dgdg1", "url":"https://someimagepath" } }
请问为何会自动给image对象添加stability字段?
原因及解决方案
原因
stability字段是Kotlin的@Parcelize注解自动生成的。当用@Parcelize实现Parcelable接口时,Kotlin编译器会在生成的字节码中添加这个字段,用于处理序列化的稳定性(比如类结构变化时的兼容性)。Firestore在序列化对象时,会通过反射遍历对象的所有公共属性(包括编译器自动生成的),因此这个额外字段被写入到了Firestore文档中。
解决方法
有几种方式可以避免这个问题:
手动实现Parcelable接口
放弃使用@Parcelize,手动编写Parcelable的实现代码,这样就不会生成额外的stability字段:data class Image(val id: String = "", val url: String = "") : Parcelable { constructor(parcel: Parcel) : this( parcel.readString() ?: "", parcel.readString() ?: "" ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeString(id) parcel.writeString(url) } override fun describeContents(): Int { return 0 } companion object CREATOR : Parcelable.Creator<Image> { override fun createFromParcel(parcel: Parcel): Image { return Image(parcel) } override fun newArray(size: Int): Array<Image?> { return arrayOfNulls(size) } } }使用Firestore自定义转换器
保留@Parcelize,但为Image类创建Firestore转换器,只序列化需要的id和url字段:class ImageConverter : FirebaseFirestoreConverter<Image> { override fun toFirestore(image: Image): Map<String, Any> { return mapOf( "id" to image.id, "url" to image.url ) } override fun fromFirestore(snapshot: Map<String, Any>, options: SnapshotOptions): Image { return Image( snapshot["id"] as? String ?: "", snapshot["url"] as? String ?: "" ) } }使用时指定转换器:
// 注册Collection引用时绑定转换器 val collection = firestore.collection("collectionname").withConverter(ImageConverter()) // 存储数据 collection.document(documentId) .set(mapOf( "title" to "My Title", "image" to Image("dgdg1","https://someimagepath") ), SetOptions.merge()) .await()分离数据类职责
创建两个类:一个用于Parcelable传输的Image类(保留@Parcelize),一个专门用于Firestore存储的ImageDto类,存储时将Image转换为ImageDto:@Parcelize data class Image(val id: String = "", val url: String = "") : Parcelable data class ImageDto(val id: String = "", val url: String = "") // 存储时执行转换 data["image"] = ImageDto(image.id, image.url)
内容的提问来源于stack exchange,提问作者BalaramNayak
相关产品推荐
相关产品推荐

