Realm meetup #8 参加レポート
2015/10/27、話題のモバイルデータベース技術 “Realm” のミートアップイベントである Realm meetup #8 が、 Sansan 株式会社を会場に行われました。今回は Reporter 枠というイベントの様子をレポートする代わりに優先的に参加できる枠を使っての参加ですので、イベントレポートを書きたいと思います:)
Realm Recent Updates
まずは Realm の岸川さんと山﨑さんから、 Realm Objective-C, Realm Swift, Realm Java の最近のアップデートについて発表がありました。
iOS
Realm iOS は最近 0.96.2 にアップデートされ、様々な機能強化がアナウンスされました。
- Xcode 7.1 でビルドされ、 Carthage や Pre-build バイナリを使っている場合もリンクできるようになった
- NULL プロパティがサポートされた
- キーパス・コレクション・クエリに対応した
- エラーハンドリングが改善された
また、注意点として、NULL 対応が入ったことで Realm の DB ファイルフォーマットが新しいものになり、ほとんどの場合でマイグレーションが必要になるそうです。
Objective-C 版でマイグレーションを行わずに対応するには、クラスメソッドである +(NSArray *) requiredProperties
を使うと良いとのことでした。
Swift 版では Swift の構文である Optional がそのまま利用できるようです。
dynamic var name = "" // not null
dynamic var birthday: NSDate? // nullable
その他、詳しくはニュースリリースを見ると良いでしょう。
また、新型 Apple TV に搭載されている tvOS 対応も進められていて、とても興味深い話が展開されました。 GitHub の Issues 2691 で対応が進められているそうなので、興味がある方はウォッチしておくと良いでしょう。
Android
10 月から Realm の活動に加わった株式会社ウフィカの山﨑さんから、最近の Realm Java の報告がありました。
Realm Java 0.84.0 が最近リリースされ、 iOS 同様に様々な機能強化がアナウンスされました。
- NULL プロパティサポート (0.83)
- プリミティブラッパークラスサポート (0.83)
- 非同期クエリ・トランザクションサポート (0.84)
NULL プロパティサポートは iOS 同様に null を DB に格納できるようになるもので、やはり DB ファイルフォーマットが変更されているので、一度アップデートすると下のバージョンに戻せなくなるので注意が必要とのことでした。
フィールドに @Required
アノテーションを付けると、これまでのバージョン同様に null を入れることができないフィールドになるそうです。
また、 int や long のようなプリミティブ型のラッパークラスである Integer や Long なども対応され、こちらのラッパークラス型を使うことで null がサポートされるそうです。
そして、 Realm Java が先行した機能として非同期クエリ・トランザクションサポートがアナウンスされました。これは、クエリ処理、トランザクション処理をワーカースレッドで行い、結果の通知を受け取ることができるというものです。
Realm のスピードであれば、ほとんどの場合 UI スレッドで処理を行っても大丈夫ですが、10 万近いデータ量を処理したり、複雑なクエリを発行する場合に効果があるとのことでした。
これらについても、ニュースリリースが詳しいです。
そして個人的にとても楽しみな発表として、 RxJava 対応の検討が Pull Request で開始されたそうです。これまでは Realm で管理するオブジェクトと、プレーンなバリューオブジェクトを駆使して RxJava に対応するしかなかったので、公式に対応が進んだら嬉しいですね。
アプリ開発初心者における Realm 導入事例
エキサイト株式会社の渡辺さん (先日、 Swift 2 標準ガイドブックを共著で執筆されたそうです) から、 Realm をエキサイト社内のアプリで採用した事例について発表がありました。
印象的だった話題として、"女子トピ“ という女性向けアプリでは CoreData でほぼ実装が終わっていたところを、 Realm で全て再実装し直したというものがありました。
これは、実装したは良いものの CoreData の使い方に不安があったとのことでしたが、導入のきっかけでお話しになっていた
- ドキュメントが分かりやすく、日本語版もある
- CoreData よりも学習コストが低い
- やりたいことがサンプルコードに書いてある
という点がポイントだったのかなと思います。また、
- 新規アプリの場合、積極的に検討する価値がある
- 既存アプリで使う場合でも、影響範囲の少ない箇所から移行すると良い
- 驚くほど簡単に導入できた
というのも印象的でした。簡単に使えて、ハイパフォーマンスというところが Realm の良いところのようです。
日経電子版アプリが高速化のためにやったこと
株式会社日本経済新聞社の武市さんから、今年の4月にリニューアルされた、日経電子版アプリの高速化についての発表がありました。
日経電子版は 2010 年に最初のアプリをリリースされたそうですが、完全外注で、ボタン1つを追加するにも要件定義や稟議など、多くの手間が発生していたところに内製化を提案し、スタートしたそうです。
当初、起動してから画面が表示されるまでに相当な時間がかかっていたそうで、これは初期化時に取得するデータが 32MB もあったからだそう。記事データと画像が入った zip ファイルをダウンロードして、アプリ内に展開する処理が大変な不可だったようです。
なので、最初は画像を都度取得するようにしたり、記事自体も1つの大きな JSON にせず、マスターデータと記事単体の JSON に分割してあるものを使うようにするなどして高速化をはかるようにしたところ、取得データ量が 32MB から 4 〜 7 KB になったとのことでした。
また、 CoreData では関連を付けたオブジェクトを 500 件ほど保存したところで急激にパフォーマンスが落ちたそうですが、 Realm に移行した後は問題が無いとのこと。日経電子版では関連を付けたオブジェクトが多数あるため、 CoreData は向いていなかったようです。
iPhone 4 / iOS 7 の環境で CoreData では 32.16s かかっていた処理時間が、 Realm にしてからは 4.68s にまで削減され、社内からも喜びの声が上がったという話が印象的でした。
その他
気になったことがあったので質問をしてみました。
Fine Grained Notification の状況はどうか?
Fine Grained Notification は Realm のオブジェクトに変化があったことを通知するより良い仕組みのことで、今は何かがあったという通知を受け取ることができないのですが、 FGN が搭載されれば、どのオブジェクトがどう変わったのかを受け取ることができるようになります。
個人的にとても楽しみにしているのですが、ここしばらく動きが見られなかったため聞いてみたところ、 Realm Core 側の変更なども絡んでくるため、想定以上に難しい状況とのこと。 Realm Version 1.0 の中にも入らない可能性が高いそうです。
Android で使う場合、 Activity / Fragment で Realm オブジェクトをどう持つべきか
Activity では
private Realm mRealm;
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRealm = Realm.getDefaultInstance();
}
@Override
protected void onDestroy () {
mRealm.close();
super.onDestroy();
}
Fragment では
private Realm mRealm;
@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState);
mRealm = Realm.getDefaultInstance();
return view;
}
@Override
public void onDestroyView () {
mRealm.close();
super.onDestroyView();
}
このようなタイミングで持つと良いとのことでした。また、それ以外では
Realm realm = Realm.getDefaultInstance();
try {
// do it
} finally {
realm.close();
}
のように、try-finally を使って、close を確実に行うことを徹底するべきとのことでした。 Android 4.4 以降であれば try-with-resources 構文が使えますが、さすがにまだ 4.4 以降をターゲットにアプリを書くことが難しいので、しばらくは try-finally で close を忘れずに行うことになりそうです。