LoginSignup
86
82

More than 5 years have passed since last update.

Kotlin + Realm Java がさらに使いやすくなった件について

Last updated at Posted at 2015-06-23

はじめに

Realm Javaが0.81.1にアップデートされ、ついについにKotlinがサポートされました。
KotlinがKaptをリリースしたのでRealmがフルことりんで使える日が来るのは時間の問題だろうと(勝手に)思っていましたがついにです!

Realm Java 0.81.1 - Realm is a mobile database: a replacement for SQLite & Core Data

準備

KotlinでAnnotation Processorを使うにはbuild.gradleでkaptの指定が必要です。
公式のKotlinサンプルのbuild.gradleを参考にしつつ、ローカルのjarを使っている箇所をMavenから取得するように変更します。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'io.realm:realm-android:0.81.1'
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

    kapt 'io.realm:realm-android:0.81.1'
}

モデルクラスをKotlinで書く

今までもKotlinでRealmを使うことはできていましたが、唯一出来なかったのがモデルクラスをKotlinで書くことです。
まずは既存のJavaのモデルクラスをKotlinに変換してみます。

例えば、次のようなモデルをKotlin変換にかけてみます。

public class Cat extends RealmObject {
    public String name;
    public int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

変換結果は次のようになるはずです。

public class Cat : RealmObject() {
    public var name: String
    public var age: Int = 0
}

Kotlinではフィールドのgetter/setterは内部的に作成されているのでかなりスッキリですね!最高ですね!
ただ、これで万事オーケーかというと残念ながら修正が必要です。
ポイントとしては

  1. Kotlinでは基本的にはフィールドに初期値を入れる必要がある(但しRealmでは使われない)
  2. クラスおよびフィールドにopenアクセス修飾子が必要
    • Kotlinではデフォルトでクラスの継承が許可されていない(final) → Realmがプロキシクラスを作れない
  3. クラスにRealmClassアノテーションを付ける必要がある

上記を踏まえて修正すると次のようになります。
今回nameはNullableにしていますがString?Stringにすれば当然Nullが許容されなくなります。

RealmClass
public open class Cat : RealmObject() {
    public open var name: String? = null
    public open var age: Int = 0
}

Kotlinらしいモデルクラス

公式サンプルにもあるのですが、Kotlinのデフォルトコンストラクタのプロパティを使った書き方が出来ます。

RealmClass
public open class Cat(
        public open var name: String = "Mike",
        public open var age: Int = 6
) : RealmObject() {}

このような書き方をすることでStandaloneオブジェクト経由にはなってしまいますが、初期値を指定&コンストラクタの名前付き引数で必要な場所だけ値を変更ということができるようになります。

使用例

ここまで来れば次のように使うことができます。

    // closable なインスタンスは use ブロックを使えば勝手にcloseしてくれる!
    Realm.getDefaultInstance().use { realm ->
        realm.executeTransaction {
            // Tamaを作る(通常の作り方、どちらのパターンのモデルでも可)
            val cat1 = realm.createObject(javaClass<Cat>())
            cat1.name = "Tama"
            cat1.age = 3
            // Mikeを作る(Standaloneオブジェクト経由の作り方、2番目のパターンのモデルでのみ可)
            val cat2 = Cat(age = 2)
            realm.copyToRealm(cat2)
        }
        // Catテーブルを全件取得して名前と年齢をログに出力
        realm.where(javaClass<Cat>()).findAll().forEach {
            Log.d("RealmWithKotlin", "${it.name} is ${it.age} years old.")
            // Tama is 3 years old.
            // Mike is 2 years old.
        }
    }

おわり

いままでもモデルだけJavaで書いて残りはKotlinという構成でもかなり使い勝手の良かったRealmですが、今回のKotlinサポートでモデルまでまるっとすべてKotlinでスッキリと書けるようになりました。最高です。

Kotlinかわいいよかわいいよ!Realmいいよ!

86
82
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
86
82