※ これは[Android その2 Advent Calendar]( Android その2 Advent Calendar 2017 - Qiita )の10日目の記事です。
2017/12/05にRealm 4.3.0が発表されました!
このアップデートでRealm + Kotlinが強化されたので紹介です!
Overview
-
T::class.java
なんてもう書かないで良いよ! -
RealmModel
のメソッド呼び出しが美しく書けるよ! - Kotlinで
in
は予約語だよねoneOf
使って良いよ!
T::class.java
なんてもう書かないで良いよ!
いままでは
Kotlinを使っている場合、Realmでクエリを記述は以下のようになります。(公式引用)
// Instead of this…
val dog = realm.createObject(Dog::class.java) // create a Dog
realm.delete(Dog::class.java) // Delete All Dogs
realm.where(Dog::class.java)
.findAllAsync()
.asFlowable() // Fetch all dogs asynchronously as an RxFlowable
これらの引数にはJavaのClassインスタンスを渡す必要があるためです。
ちょっと気持ち悪いですよね。
これからは
reified type paramter
を用いた拡張関数の定義により
// You do this
val dog = realm.createObject<Dog>() // create a Dog
realm.delete<Dog>() // Delete All Dogs
realm.where<Dog>()
.findAllAsync()
.asFlowable() // Fetch all dogs asynchronously as an RxFlowable
のように記述できます!(公式引用)
これに尽きちゃうのですが、簡単に実装を見てみましょう。
Extensionの実装
恩恵をうけるのは以下のメソッドになります。
- where
- delete
- createObject
ここではwhere
を見てみることにします。
inline fun <reified T : RealmModel> Realm.where(): RealmQuery<T> {
return this.where(T::class.java)
}
見て取れる通り、reified
を使ってJavaのClassインスタンスを取得することで実現しているようです。
Reified Type Parametersは関数の中でT
を実際の型として扱える機能ですね。便利だ…
RealmModel
のメソッド呼び出しが美しく書けるよ!
補足
Realmでは、RealmObject
クラスを継承することでモデルを定義します。
open class Example(
open var name: String = "",
open var status: Int = 0,
) : RealmObject() {}
アプリによっては、別のベースモデルクラスを継承させたいという場面はよくあるとおもいますが、
この場合、RealmObject
を継承する以外の選択肢としてRealmModel
インタフェースと@RealmClass
アノテーションを用いる方法があります。
これを用いると
@RealmClass
open class Example(
open var name: String = "",
open var status: Int = 0,
) : RealmModel {}
のようになります。
いままでは
RealmObject
がインスタンスメソッドとして提供していたメソッドは、提供されているstaticメソッドを利用する必要がありました。
// RealmObjectを継承する場合
example.isValid()
example.addChangeListener(listener)
// RealmModelを実装する場合
RealmObject.isValid(example)
RealmObject.addChangeListener(example, listener)
これからは
拡張メソッドとして提供され、RealmModel
を実装させた場合でも
@RealmClass
open class Example(
open var name: String = "",
) : RealmModel {}
example.isValid()
example.addChangeListener(listener)
のように記述することができます!美しい!!
こちらも簡単に実装を見てみましょう。
Extension実装
恩恵をうけるのは以下のメソッドになります。
- deleteFromRealm
- isValid
- isManaged
- isLoaded
- load
- E.addChangeListener
- E.removeChangeListener
- removeAllChangeListeners
ここではdeleteFromRealm
を見てみることにします。
fun RealmModel.deleteFromRealm() {
RealmObject.deleteFromRealm(this)
}
簡単なExtensionですが、圧倒的に美しくなりますね。感謝。
Kotlinでin
は予約語だよねoneOf
使って良いよ!
いままでは
Kotlinではin
が予約語のため、クエリで使用する場合以下のように書く必要があります。(公式引用)
val dogs = realm
.where<Dog>()
.`in`("name", arrayOf("Larry", "Curly", "Moe"))
これからは
oneOf
という拡張メソッドにより以下のように記述できます。(公式引用)
val dogs = realm
.where<Dog>()
.oneOf("age", arrayOf("Larry", "Curly", "Moe"))
※ 注釈
Realmの公式ブログではanyOf
を追加したよ!と記載されていますが、誤植?でしょうか。。
anyOf
は実装されていないのでoneOf
を使いましょう!
Extension実装
String
の比較を行う場合の実装を見てみます。
fun <T : RealmModel> RealmQuery<T>.oneOf(propertyName: String,
value: Array<String?>,
casing: Case = Case.SENSITIVE): RealmQuery<T> {
return this.`in`(propertyName, value, casing)
}
ちょっとしたことですが、Kotlinでの実装が気持ちよくなりますね!!
まとめ
著名なライブラリがKotlinで使いやすいようアップデートするケースを最近良く見ますね!
Kotlinはきもちよく書きたいですよね!素敵!!