しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

Android用Realmの導入とbuild.gradleについてのメモ

今回はRealmの導入をしてみました。
それに合わせてbuild.gradleについて分からない所の簡単な調査も行いました。

インストール手順は公式サイトを参考にしました。

www.mongodb.com

インストール

まずは下のようにプロジェクトトップにあるbuild.gradleのpluginsにRealmを追加します。

plugins {
    id 'com.android.application' version '7.1.2' apply false
    id 'com.android.library' version '7.1.2' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
    id 'io.realm.kotlin' version '0.10.0' apply false // 追加
}

次はappフォルダのbuild.gradleのpluginsにもRealmを追加します。

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'io.realm.kotlin' // 追加
}

最後にdependencies同ファイルのdependenciesに下2行を追加します。

dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt' // 追加
    implementation 'io.realm.kotlin:library-base:0.10.0' // 追加
    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

入れ終わったら「Sync Project with Gradle Files」をしてインストール完了です。

動作確認

インストールが終わったら簡単に動かしてみます。
動作確認は下サイトを参考にしました。

www.mongodb.com

モデルの定義方法は下の通りです。

class Task : RealmObject {
    var name: String = "new task"
    var status: String = "Open"
}

データの取得は下の通りです。

val config = RealmConfiguration.Builder(schema = setOf(Task::class)).build()
val realm: Realm = Realm.open(config)
var tasks: RealmResults<Task> = realm.query<Task>().find()

データ保存は下の通りです。

val config = RealmConfiguration.Builder(schema = setOf(Task::class)).build()
val realm: Realm = Realm.open(config)
realm.writeBlocking {
    copyToRealm(Task().apply {
        name = "Do work"
        status = "Open"
    })
}

上記を動かしてみた所、無事に保存と取得ができていました。

build.gradleについてのメモ

build.gradleですが、プロジェクト直下とapp直下の2箇所にあります。
この2つの違いですが、プロジェクト直下は全サブプロジェクトやモジュール向け・app以下はサブプロジェクト(app以下)向けの処理を書くというもののようです。

次はプロジェクト直下build.gradleに記述した処理について見ていきます。
pluginsのブロックですが、こちらにはGradle依存関係を定義します。
定義は下のようにidメソッドを使って行います。

plugins {
    id 'io.realm.kotlin' version '0.10.0' apply false
}

applyについてはGradleのサイトを見た所、下のように書かれていました。
見た所、applyはプラグインの即時適用をするかどうかを決める事ができるもののようです。
即時適用しないことで「特定のサブプロジェクトにだけ導入する」といった事ができます。
ちなみにこれは除外しても問題なく動きました。

Where «plugin id» and «plugin version» must be constant, literal, strings and the apply statement with a boolean can be used to disable the default behavior of applying the plugin immediately (e.g. you want to apply it only in subprojects). No other statements are allowed; their presence will cause a compilation error.

Using Gradle Plugins

次はapp直下のbuild.gradleについて見ていきます。
まずは先程も出てきたpluginsについて調べます。

plugins {
    id 'io.realm.kotlin'
}

こちらについてはGradleのサイトに記述がありました。
プロジェクト直下のpluginsでapply falseをして、こちらにも記述する事でライブラリが使えるようになる模様です。

If you have a multi-project build, you probably want to apply plugins to some or all of the subprojects in your build, but not to the root project. The default behavior of the plugins {} block is to immediately resolve and apply the plugins. But, you can use the apply false syntax to tell Gradle not to apply the plugin to the current project and then use the plugins {} block without the version in subprojects' build scripts:

もしこの処理を書かないと下のようにapplyされていないというエラーになります。

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapp/com.example.myapp.MainActivity}: java.lang.IllegalStateException: Couldn't find companion object of class 'Task'.
A common cause for this is when the `io.realm.kotlin` is not applied to the Gradle module that contains the 'Task' class.

その後プロジェクト直下のbuild.gradleのapplyをtrueにしたのですが同じエラーが出ました。
どうやらモジュールのbuild.gradleでapplyしないと正しく動かない模様です。
もしくはキャッシュなどが残っているせいかもしれません。

plugins {
    id 'io.realm.kotlin' version '0.10.0' apply true
}

app直下の方でapply falseをつけた場合も同じエラーになります。
apply自体はしっかり動いている模様です。

plugins {
    id 'io.realm.kotlin' apply false
}

それとapp直下でversionを指定した場合、既にバージョンが指定されているエラーになります。
ただプロジェクト直下のidをコメントアウトした場合はエラーが出ずに正しく動かす事ができました。

plugins {
    id 'io.realm.kotlin' version '0.10.0'
}
Error resolving plugin [id: 'io.realm.kotlin', version: '0.10.0']
> Plugin request for plugin already on the classpath must not include a version

最後にapp直下build.gradleのdependenciesブロックについて見ていきます。
調べた所、コンパイル時や実行時に外部クラスを読み込むのに必要な処理のようです。
ただpluginsでのapplyとdependenciesの両方必要な理由が良く分かりませんでした。
この辺りはまた時間ある時に調べてみたいと思います。

dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt'
    implementation 'io.realm.kotlin:library-base:0.10.0'
}

ビルド依存関係を追加する  |  Android デベロッパー  |  Android Developers

ちなみにこの処理をコメントアウトするとRealmのライブラリが読めないエラー(Unresolved reference: io)が出ます。

参考URL

ビルドを設定する  |  Android デベロッパー  |  Android Developers