Realm Blog

Realm Javaのセットアップ方法が変わります

これまでのRealmの制限事項

Realm for Androidをリリースしてからのこの1年、ライブラリにはいくつかの制限があるにもかかわらず高い評価をいただきました。

Realm for Androidの制限事項の中でも、RealmObjectを継承したクラスに課せられる以下のような制約に対する多くのご要望をいただきました。

  • publicなフィールドを持つことができない
  • アクセッサのメソッド名が標準的なものに限られている
  • アクセッサに独自のロジックを持つことができない
  • カスタムメソッドを持つことができない
  • メソッドを持つinterfaceを実装することができない

これらの制限事項はある共通の理由に由来しています。それは、Realmがデータストアに対するzero-copyオペレーションを実現するためにproxyクラスを使用しているということです。

それでは、これらの制限事項を一つずつ見ていきましょう。

publicなフィールドを持つことができない点について

Java言語はフィールドに対するアクセスを横取りすることを可能にする言語仕様を持っていないので、フィールドに対するアクセスに対してRealmのproxyクラスが割り込むことができません。また、フィールドの情報はJavaヒープ上に保持されることが言語仕様で定められています。このことにより、フィールドへの直接アクセスを許してしまうとRealmの情報をフィールドにコピーしなければならないことになり、zero-copyではなくなってしまいます。

アクセッサのメソッド名が標準的なものに限られている点について

アノテーションプロセッサはとても強力なツールですが、いくつかの制限も存在しています。そのうちの一つに、proxy対象のクラスのフィールドやメソッドの名前は取得できるが、メソッド内の処理内容を取得できないというものがあります。そのため、Realmのproxyクラスが意図通りに動作するかは利用者が規約に従った実装を行っているかに依存します。

アクセッサに独自のロジックを持つことができない点について

これは一つ前の項目から導かれる制限です。アノテーションプロセッサはアクセッサの実装内容を取得することができないので、proxyクラスにその実装内容を取り込むことができません。もちろん単にsuper.getMyField()を呼び出すことはできますが、この呼び出しはメモリー上のデータに対する操作であり、proxyクラスが対象とするRealmのデータを対象とするものにはなりません。

カスタムメソッドを持つことができない点について

繰り返しになりますが、アノテーションプロセッサはコードの内容を取得することができないので、カスタムメソッドが実装に行っている処理を把握することができません。このようなメソッドを許してしまうと正しく動作することを保証できなくなってしまうため、Realmはそのようなメソッドを許容していません。

メソッドを持つinterfaceを実装することができない点について

カスタムメソッドを許容しないという制限により、メソッドの実装が必要なinterfaceについては許容されません。

制限事項の解消に向けて

これらの制限事項を解消する唯一の方法は、バイトコード変換を使用することです。これは、ソースコードのコンパイルで生成された.classファイルに対して加工を行うことを意味しています。どのような加工を行うかについては別の記事での解説を予定しているので、ここでは詳細については割愛します。重要なことは、Gradleプロジェクトでバイトコード変換を行うためには、Gradle pluginが必要であるということです。これはRetroLambdaHugoなどが行っている方法です。

build.gradleの記述方法の変更

これまでは、以下のように設定することでRealmを使用していました。

repositories {
    jcenter()
}

dependencies {
    compile 'io.realm:realm-android:<version>'
}

これを、以下のようにRealmのGradleプラグインを使用する方式に書き換える必要があります。

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'io.realm:realm-gradle-plugin:<version>'
    }
}

apply plugin: 'realm-android'

大部分のコードはすでにbuild.gradleにすでに記述があると思うので、classpathapply plugin: 'realm-android'の行を追加してください。

なぜ今変更するのか

なぜまだバイトコード操作方式がリリースされてないこのタイミングでプラグインを提供しはじめるのでしょうか?

これにはバイトコード操作以外にも理由があるからです。

APKサイズの削減!

プラグインを使用することで、AAR形式のRealmを簡単に使用することができるようになります。また、アノテーションプロセッサのクラスがライブラリ本体から分離されます。このことは、生成されるAPKファイルにはアノテーションプロセッサのクラスが含まれなくなることを意味し、数Kバイトではありますが、サイズが削減できます。

ABI splitsを簡単に!

AAR形式のRealmを利用できるようになる事の別の利点として、これまでABI splitsを使用する際に必要であったワークアラウンドが不要になります。これにより、すべてのCPUアーキテクチャ用のネイティブライブラリが含まれた巨大なAPKで配布する必要はなくなります。

Eclipseはどうなるのでしょうか?

おそらくご存知だ思いますが、GoogleはADT plugin for Eclipseを非推奨としてすでにサポートを終了しています。そのため多くのAndroid開発者はすでにAndroid Studioへの移行を完了しており、我々が注力すべきもそちらであると考えています。 ただし、何を優先すべきかは開発者の皆様からのフィードバックによって決まります。そのため、AntやMavenのpluginに対する多くの要望が集まるようであれば、優先度ついて再検討を行う可能性があります。

Happy Coding!

この変更により、開発者の皆様により快適に開発を行っていただけるものと期待しています。ご意見やご要望がありましたらSlack(日本語)Twitter(日本語)Stack Overflow(日本語), GitHub(英語)で遠慮なくお知らせください。


Realm Team

At Realm, our mission is to help developers build better apps faster. We provide a unique set of tools and platform technologies designed to make it easy for developers to build apps with sophisticated, powerful features — things like realtime collaboration, augmented reality, live data synchronization, offline experiences, messaging, and more.

Everything we build is developed with an eye toward enabling developers for what we believe the mobile internet evolves into — an open network of billions of users and trillions of devices, and realtime interactivity across them all.

記事の更新情報を受け取る