【发布时间】:2017-08-01 22:14:13
【问题描述】:
我正在使用 Kotlin 对象来处理我的 Firebase 数据库模型,如 in the guide 所述。我有很多存储为字符串的字段,但实际上是枚举,所以为了类型安全,我在模型中有枚举字段,加上一个返回 firebase 存储值的字符串委托属性(如前段时间a question I asked 中所建议的那样)。现在,如果我在代码中获取/设置字符串委托,这些字段就可以工作,但是在转换到/从数据库的 json 格式转换时,firebase 库似乎会跳过它们。
一个简单的例子:
abstract class BaseModel {
@Exclude
open var path: String? = null // fails even if I delete this field!
}
class Weight() : BaseModel() {
constructor(v: Double, u: WeightUnit) : this() {
value = v
unitEnum = u
}
var value: Double = 0.0
@Exclude
var unitEnum: WeightUnit = WeightUnit.KG
var unit: String by EnumStringLowercaseConverter(WeightUnit::class.java).getDelegate(Weight::unitEnum)
}
[...]
val testWeight = Weight(7.0, "kg")
db.getReference("/valid/path/to/save/testWeight").setValue(testWeight)
.addOnSuccessListener { r -> Log.d(LOG_TAG, "set successful") }
.addOnFailureListener { e -> Log.e(LOG_TAG, "set error", e) }
setValue 总是给出 Permission Denied 错误,但如果我删除 unitEnum 字段并将 unit 设置为正常的 String 属性,则可以正常工作。
读取时类似:Firebase 在获取 Weight 对象时没有给出错误,但 weightUnit 字段从未设置为默认值以外的任何值。但是,如果我手动执行weight.unit = "lb",unitEnum 字段会正确返回WeightUnit.LB。
我正在使用 firebase 库 v10.0.1
现在,问题:
- 如何使委派属性与 Firebase 一起正常工作?只要满足my original question 中的点(可读、简洁和类型安全的代码),我就可以尝试对委托枚举字段使用不同的方法。
- 有什么方法可以了解 Firebase 库如何准确将对象转换为 json 或从 json 转换对象?或者至少看到转换后的 json?也许那时我可以自己调整一些东西。不幸的是,所有与 firebase 相关的内容在 AndroidStudio 中都显示为
/* compiled code */。
更新:我当然可以为每个模型添加一个 toMap() 方法,在其中我将构建一个包含 firebase 所需的所有属性的地图,但对每个模型都这样做会很烦人模型,并且只解决了保存问题,获取时仍然不会设置枚举字段。
使用 GSON 序列化时也会跳过委托的道具。那么也许有一种通用的方法可以使委托属性看起来像常规字段?
【问题讨论】:
-
GSON 不允许序列化函数,以及委托的扩展 getter/setter。一种可能的解决方案是让 unitEnum 成为一个委托,它在更新时也会更新单位字符串。
var unitEnum: WeightUnit by EnumStringUpdate(WeightUnit::class.java).getDelegate(Weight::unit) -
::class.java已弃用,请使用.javaClass
标签: android firebase firebase-realtime-database kotlin