2017-01-14 5 views
6

Firebase上の私のデータは、文字列型のフィールドを多く使用しますが、実際には列挙型の値です(これは私の検証ルールでチェックします)。データをAndroidアプリにダウンロードするにはfollowing the guide、フィールドは基本Stringである必要があります。私は列挙型である2番目のフィールド(除外されたフィールド)でこれを回避でき、このベースを文字列値に設定できることを知っています。短い例:Firebase:Kotlin/Javaで列挙型フィールドを使用するためのきれいな方法?

class UserData : BaseModel() { 
    val email: String? = null 
    val id: String = "" 
    val created: Long = 0 
    // ... more fields omitted for clarity 
    @Exclude 
    var weightUnitEnum: WeightUnit = WeightUnit.KG 
    var weightUnit: String 
     get() = weightUnitEnum.toString() 
     set(value) { weightUnitEnum = WeightUnit.fromString(value) } 
} 

enum class WeightUnit(val str: String) { 
    KG("kg"), LB("lb"); 
    override fun toString(): String = str 
    companion object { 
     @JvmStatic 
     fun fromString(s: String): WeightUnit = WeightUnit.valueOf(s.toUpperCase()) 
    } 
} 

、これは動作しますが、それは本当にきれいではありません。

  • enum class自体が(2)内部が繰り返される、(1)ちょっと長い 列挙型のためにありますすべての列挙型。そして私はそれらの多くを持っています。
  • enumsだけでなく、上記のcreatedフィールドは実際にタイムスタンプです ではなくLongです。
  • 各モデルは...
  • helperフィールド/機能が大幅に悪化している/長いフィールドのためのそのようなMap<SomeEnum, Timestamp>ようなタイプで...
  • これらの列挙型は、反復コードとモデルクラスをbloats多くの時間を、フィールド使用しています

これを正しく行う方法はありますか?おそらくいくつかの図書館?あるいは、文字列を列挙型やタイムスタンプなどに自動的に変換する魔法の "フィールドラッパー"を書く何らかの方法ですが、データを取得/設定するためのFirebaseライブラリとはまだ互換性がありますか?

(Javaソリューションが:)あまりにも歓迎されている)

答えて

4

あなたenum値とStringタイプの別のプロパティを持つプロパティの間の変換が十分であれば、これは簡単にKotlin delegated propertiesを使用して柔軟な方法で行うことができます。短いそれを言う

、あなたは変換を実行し、実際に/がenum値を格納する別のプロパティの値を設定し、それにStringプロパティを委任取得Stringプロパティのデリゲートを実装することができます。

1つの可能な実装は、次のようになります。

class EnumStringDelegate<T : Enum<T>>(
     private val enumClass: Class<T>, 
     private val otherProperty: KMutableProperty<T>, 
     private val enumNameToString: (String) -> String, 
     private val stringToEnumName: (String) -> String) { 

    operator fun getValue(thisRef: Any?, property: KProperty<*>): String { 
     return enumNameToString(otherProperty.call(thisRef).toString()) 
    } 

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { 
     val enumValue = java.lang.Enum.valueOf(enumClass, stringToEnumName(value)) 
     otherProperty.setter.call(thisRef, enumValue) 
    } 
} 

注:このコードは、プロジェクトの依存関係として、KotlinのリフレクションAPI、kotlin-reflectを追加する必要があります。 Gradleではcompile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"を使用します。

このは、以下に説明するが、最初に私が直接インスタンスを作成しないように便利なメソッドを追加してみましょうされます。

inline fun <reified T : Enum<T>> enumStringLowerCase(
    property: KMutableProperty<T>) = EnumStringDelegate(
    T::class.java, 
    property, 
    String::toLowerCase, 
    String::toUpperCase) 

をそして、あなたのクラスの使用例:

// if you don't need the `str` anywhere else, the enum class can be shortened to this: 
enum class WeightUnit { KG, LB } 

class UserData : BaseModel() { 
    // ... more fields omitted for clarity 
    @Exclude 
    var weightUnitEnum: WeightUnit = WeightUnit.KG 
    var weightUnit: String by enumStringLowerCase(UserData::weightUnitEnum) 
} 

今説明:

var weightUnit: String by enumStringLowerCase(UserData::weightUnitEnum)と記述すると、Stringプロパティを委任します。 yを作成したデリゲートオブジェクトに渡します。つまり、プロパティにアクセスすると、代わりにデリゲートメソッドが呼び出されます。また、デリゲートオブジェクトは、フードの下のweightUnitEnumプロパティで動作します。

私は便利機能(reified type parameterを使用)プロパティ宣言のサイトでの書き込みUserData::class.javaの必要性からあなたを節約し、(あなたが任意の時点で異なる変換を持つ他の関数を作成し、あるいは作ることができますEnumStringDelegateへの変換機能を提供変換関数をラムダとして受け取る関数)。 「

基本的に、このソリューションは、変換ロジック与え、Stringプロパティとしてenum型のプロパティを表し、定型的なコードからあなたを節約し、あなたがドン場合も、あなたはenumに冗長なコードを取り除くことができますそれ以外の場所では使用しないでください。

このテクニックを使用すると、の数値からタイムスタンプのようなプロパティ間の変換を実装できます。

+0

私はあなたのアドバイスに基づいて何かを実装しましたが、最終的にオブジェクトのデータベースへの保存/保存時に委任されたプロパティがFirebaseライブラリによってスキップされているようです。あなたはおそらくこれを回避する方法を考えていますか?詳細:https://stackoverflow.com/questions/42737499/firebase-db-models-with-kotlin-delegated-properties – quezak

+0

@quezak '@ PropertyName'を使用してみてください:http://stackoverflow.com/questions/38681260/ firebase-propertyname-doesnt-work私はFirebaseの経験はありませんが、デフォルトではフィールドのみで動作するようです。 – hotkey

1

私は同様の状況にあります。&はあなたの質問に加えて、他の同様の質問/回答をたくさん見つけました。

私は自分のアプリを変更することにしました。& enumデータ型をまったく使用していません - 主にenumがどれほど悪いのかを示すGoogle devポータルのアドバイスアプリのパフォーマンス以下のビデオを参照してくださいhttps://www.youtube.com/watch?v=Hzs6OBcvNQE

関連する問題