2017-03-11 12 views
2

in the guideと記載されているように、私はFirebaseデータベースモデルで作業するためにKotlinオブジェクトを使用しています。私は文字列として格納されている多くのフィールドを持っていますが、実際には列挙型ですので、型の安全性を保つためにモデルの列挙型フィールドとfirebaseの格納された値を返す文字列代理プロパティ(a question I asked)コードで文字列デリゲートを取得/設定すると、これらのフィールドが機能しますが、firebaseのlibsはデータベースのjson形式から/に変換するときにスキップするように見えます。firebase db:Kotlin代理プロパティを持つモデル

簡単な例:私はunitEnumフィールドを削除し、unit通常String財産を作る場合

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エラーを与えるが、動作します。

これは似ています:Weightオブジェクトを取得するときFirebaseはエラーを発生しませんが、weightUnitフィールドはデフォルト以外に設定されません。しかし、手動でweight.unit = "lb"を実行すると、unitEnumフィールドは正しくWeightUnit.LBを返します。

私は今firebase LIBS v10.0.1

を使用しています、質問:

  • 私は委任プロパティがfirebaseで正しく動作させるために何ができますか? my original questionからのポイント(読み取り可能、簡潔で型付き安全なコード)が満たされている限り、委任されたenumフィールドに対して別のアプローチを試みることができます。
  • どのようにすればがfirebase libsからオブジェクトをjsonに/から変換するのですか?または少なくとも変換されたjsonを参照してください?多分私は自分自身を微調整することができました。残念ながら、firebase関連のものはすべてAndroidStudioの/* compiled code */と表示されます。

UPDATE:私はもちろん、私はfirebaseに必要なすべてのプロパティを含むマップを構築するだろう各モデルにtoMap()メソッドを追加することができますが、すべてのモデルのためにこれを行うことが面倒になり、それ保存の問題のみを解決しますが、enumフィールドは取得時に設定されません。

GSONを使用してシリアル化すると、委任された小道具もスキップされます。だから、委任されたプロパティを通常のフィールドのように見せるための一般的な方法はありますか?

+1

GSONでは、シリアライズ関数や代理人の拡張子getter/settersが許可されていません。考えられる解決策の1つはunitEnumをデリゲートにすることです。このデリゲートを更新すると単位文字列も更新されます。 'var unitEnum:EnumStringUpdateによるWeightUnit(WeightUnit :: class.java).getDelegate(Weight :: unit)' – Ritave

+1

':: class.java'は廃止され、' .javaClass'を使用します –

答えて

0

このコードを試してください。うまくいくはずです。

@get:Exclude @set:Exclude 
var unitEnum: WeightUnit = WeightUnit.KG 
var unit: String 
    get() = unitEnum.name 
    set(v) { unitEnum = WeightUnit.valueOf(v) } 
+0

これは明白な解決策です。これがうまくいくことは分かっていますが、上記のリンク先の質問を見てみましょう。なぜ私はそれをしたくないのですか?https://stackoverflow.com/questions/41651507/firebase-clean-way-for-usingあなたが投稿したときに直接変換しないenumフィールドを持っている、(2)それらのフィールドがたくさんあり、コードを繰り返したくない、 (3)変換するフィールドが単純な列挙型よりも複雑です。 – quezak

+1

@quezak組み込みのfirebaseメソッドを使ってシリアライズ/デシリアライズするのではなく、 'toMap()'と 'fromMap()'メソッドを作成することを考えてください。 –

+0

はい、私は '@ StringDef'アノテーションを使用します。私の場合に適した汎用のtoMap()とfromMap()に取り組んでいますが、利点はモデルクラスでは2倍のフィールドではありませんが、読み込み/書き込み時にモデル全体を変換する必要があり、列挙型フィールドだけでなく、今のところ私のモデルは十分に小さいので、これは問題ではないはずです(そして、firebaseはおそらく同様の補完性を持っていても何らかの処理を行うでしょう) – quezak

関連する問題