今回はRealmをAndroidで使うやり方について書こうと思います
Realmの大まかな説明などは前回の記事をみてください
Realmの導入
まずはRealmを使えるようにします
build.gradle(app)で下記設定を追加します
plugin { id `realm-android` }
そして、build.gradle(Project)で下記設定を追加します
buildscript { dependencies { classpath `io.realm:realm-gradle-plugin:10.9.0` } }
設定を追加したらsyncを行うと使えるはずです。バージョンはGithubを確認してください
Modelの作成
プロジェクトで支えようになったら、まずはModelの作成からです
今回も前回と同じように仮でユーザーを表すクラスを作成します
open class User: RealmObject() { @PrimaryKey var id: Int = 0 var name: String? = null var age: Int? = null @Ignore var height: Int? = null }
RealmObjectを継承することでRealmで使えるModelになります
アノテーションで@PrimaryKey
を指定しているプロパティはプライマリーキー扱いにでき、@Ignore
を指定しているプロパティはRealmには登録されないカラムとなります
Realmのデータベースはテーブルにアクセスするために中でModelクラスを継承する必要があります
しかし、KotlinのデフォルトではJavaでいうfinalクラスで定義され、継承ができなくなってしまうので、open修飾子をつけています
Realmの初期化(起動)
Modelを初期化した後にはRealmインスタンスを初期化してDBを起動します
var relalm: Realm? = null Realm.init(this) realm = Realm.getDefaultInstance()
上記の処理をActivityやRealmを管理するシングルトンのクラスなどに追加します
ちなみにRealmを削除する場合にはclose
メソッドで行えます
RealmのCRUD
次にRealmの登録・読み取り・更新・削除についてです
読み取り
まずは読み取りです
先ほど初期化したRealmを使って読み取りを行います
// ここでのinitRealmは初期化した際のRealm initRealm.use { realm -> val result = relam.where<User>().findAll() }
findAll()
を使うことで、Realmに登録されているUserクラスのデータを全件取得できます
条件を指定する場合には下記のように条件を追加することで特定の条件のデータを取得できます
// 名前が「テスト」のデータのみ取得 val realmFilterNameData = relam.where<User>().equalTo("name", "テスト").findAll() // 名前が登録されているデータのみ取得 val realmNameNotNullData = relam.where<User>().isNotNull("name").findAll()
上記の場合だとAND条件になるので、OR条件にする場合にはgroupを指定する必要があります
relam.where<User>() .beginGroup() .equalTo("name", "テスト1") .or() .equalTo("name", "テスト2") .endGroup() .findAll()
単純に取得したデータはRealmResult
型のためListなどに変換する場合には下記のようにConvertする必要があります
initRealm.use { realm -> val result = relam.where<User>().findAll() val listResult = realm.copyFromRealm(result) }
登録・更新
登録と更新は同じ処理でできますのでまとめます
val user = User() user.id = 1 user.name = "テスト" user.age = 2 initRealm.use { realm -> realm.executeTransaction { it.insertOrUpdate(user) } }
読み取りのときと違って、realm.executeTransaction
というトランザクションの中で行わないと登録されません
insertOrUpdate
を使うことでprimaryKeyが一致しているデータがRealmに登録されている場合には更新処理が行われ、なければ登録処理が行われます
先ほどModelを作成したときにprimaryKeyを設定したのはここに理由があります。Realmに登録されているデータと一致しているかの判断基準で使われるのでprimaryKeyは設定しましょう!
また、読み取りと組み合わせて下記のように取得したデータのプロパティの更新も可能です
val results = relam.where<User>().findAll() for result in results { realm.executeTransaction { result.name = "テスト1" } }
削除
削除はrealm.deleteAllFromRealm()
でできます
val user = User() user.id = 1 user.name = "テスト" user.age = 2 initRealm.use { realm -> realm.executeTransaction { it.deleteAllFromRealm(user) } }
基本的な操作はこれだけです
Realmのデータの確認方法
実機もしくはエミュレーターで対象のアプリを起動します
AndroidStudioのView→Tool Windows→Device File Exploreを選択します。
すると上記のようにdata/data/{パッケージ名}/files
配下にrealmファイルが存在するので右クリックで別の場所に保存してリネームすればRealmファイルになります
ただし本番環境ではファイルが確認ができないためデバッグ可能になるように下記設定をbuild.gradleに追加しないとファイルを参照できないので注意が必要です
buildTypes { release { debuggable true } }
初期データを追加する
Realmファイルを追加して初期データとして扱うことができます
下記のように起動時にRealmファイルが存在しない場合には初期データをコピーしてrealmファイルとするようにできます
val congfig = RealmConfiguration.Builder() .assetFile("default.realm") // assetフォルダ配下に設定しているRealm初期データの名前指定 .name("rename.realm") // 取得できるRealmファイルの名前を変えたい場合には指定 .allowWritesOnUiThread(true) .allowQueriesOnUiThread(true) .schemeVersion(1L) .build() Realm.getInstance(config)
realmを初期化する際に設定値を変更できるのでそのタイミングでassetフォルダに格納している初期データを見るように変更します
マイグレーションについて
テーブルを追加する場合には自動的にマイグレーションされますが、変数名を変更したり、カラムを削除したりする場合には不整合のエラーが発生します
ローカルで開発している場合にはアプリを削除して新規でアプリを入れ直せばいいのですが、リリースしているアプリではそうはいきません
リリース済みのアプリではマイグレーションが必要になります
マイグレーションの処理としては下記のようなマイグレーションのクラスを作成してRealm初期化の際の設定値に追加します
// RealmMigrationクラスを継承 class Migration: RealmMigration { override fun migrate(realm: DynamicRealm?, oldVersion: Long, newVersion: Long) { val scheme = realm?.schema ?: return if (olfVersion == 0L) { scheme.create("Prefecture") // 第1引数がカラム名、第2引数がカラムの型、第3引数がぷりプライマリーキーであることの明示 .addField("id", Int::class.java, FieldAttribute.PRIMARY_KEY) .addField("sortOrder", Int::class.java) // null許容であることの明示(型がIntでNullがあり得る場合には追加する必要がある) .setNullable("name", true) oldVersion++ } } }
iOSとは違い、テーブル追加は自動でマイグレーションしないため追加する必要があります
scheme.create
がテーブル追加、addField
がカラム追加です
上記Migrationクラスを設定に追加します
val congfig = RealmConfiguration.Builder() .assetFile("default.realm") .name("rename.realm") .migration(Migration()) // 追加 .allowWritesOnUiThread(true) .allowQueriesOnUiThread(true) .schemeVersion(1L) .build() Realm.getInstance(config)
今回はスキーマのバージョンを1にアップした状態で起動時にスキーマのバージョンが0の人はマイグレーションの処理が行われます(oldVersion
がアプリ起動時のスキーマバージョンになります)
AndroidもiOSと同様に学習コストが低いので使いやすいと思います。是非試してみてください!!