はじめに
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は内部的に作成されているのでかなりスッキリですね!最高ですね!
ただ、これで万事オーケーかというと残念ながら修正が必要です。
ポイントとしては
- Kotlinでは基本的にはフィールドに初期値を入れる必要がある(但しRealmでは使われない)
- クラスおよびフィールドに
open
アクセス修飾子が必要- Kotlinではデフォルトでクラスの継承が許可されていない(final) → Realmがプロキシクラスを作れない
- クラスに
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いいよ!