Categories: Android

[kotlin] Realmでenum型を値としたモデルを作る方法 [Android]

Realmでenum使ったモデルを作りたかったのでその方法のご紹介

How to support Enums

ヒントはこちらにありました。

cf: Enums support #776 – realm/realm-java

open class Contract: RealmModel {
    enum class PaymentMethod { CREDIT_CARD, WIRE_TRANSFER }
    private var _paymentMethod: String? = null
   var paymentMethod: PaymentMethod?
        get() {
            if (_paymentMethod != null)
                return PaymentMethod.valueOf(_paymentMethod!!)
            else
                return null
        }
        set(value) {
            val realm = Realm.getDefaultInstance()
            realm.executeTransaction {
                _paymentMethod = value.toString()
            }
            realm.close()

        }
}

実態は_paymentMethodで、実際に使うときはpaymentMethodにアクセスしているみたいですね。

しかし、私の場合、EnumをIntにして使っていたのですが、上記のままではアクセスしたときに落ちてしまいました。

valueOfがどうやらうまく動いてない感じでした。

How to support Enums on Int

ということで、Intバージョンのモデルの作成方法のご紹介。

ヒントはこちらにありました。

数字から文字列を得たいとき、(例えば5を指定して, Oneを文字列として得たいとき)kotlinenum class Financing(val rawValue :Int) { One(5), Revo...
kotlinでenum classを使う - Qiita - Qiita
enum class Financing(val rawValue :Int)  {
    One(5),
    Revolving(6),
    Two(7)
}
// 使う
Financing.values().filter { 5 == it.rawValue }.first() // => One (Financing型)
Financing.values().filter { 5 == it.rawValue }.first().toString() // => One(String型)

数字からEnum型を取り出すにはfilterとかかけてうまくやらないとだめみたいです。

なんかちょっと手間ですね。

ということで、Int版の方法で書いたモデルがこちら

open class Game : RealmObject() {
    enum class PhasePoint(val integerValue: Int) {
        PLAYER_READY(1),
        GAME_START(2)
    }
    private var phaseValue: Int = PhasePoint.PLAYER_READY.integerValue
    open var phase: PhasePoint
        get() = PhasePoint.values().filter { it.integerValue == phaseValue }.first()
        set(value) {
            phaseValue = value.integerValue
        }
}

こんな感じでうまくできました

まとめ

RealmでEnum対応はできるけどちょっと手間がかかってめんどくさいかもしれない。

でも、やっぱり値をちゃんと指定できてバグがなくせるのならいいかもしれない。

mogmet

View Comments

Share
Published by
mogmet