android で realm を使ってみよう
TRANSCRIPT
RealmAndroid でRealm を使ってみようIntroduction to Realm for Android
Application Development DivisionAndroid Team, Ryutaro Miyashita
2015.03.14
RealmRyutaro MiyashitaMobile Application Engineer / ChatWork
DroidKaigi は落ちました
RealmChatWork とはビジネス向けのチャットツールです
導入社数 60,000 を突破多職種が入り交じる大きな企業や、非 IT 系の中小企業を中心に導入
利用技術はアグレッシブRealm をはじめとして、Scala や周辺 SaaS, AWS などをフル活用
Realm
Realm1. NoSQL 型の DB + ORM 2. C++ 製の Realm-Core 3. iOS /Android 両対応 4. とても速い!
RealmRealm を使ってみよう
Realm使い始めるのは簡単
Realmbuild.gradle に記述して Sync する
dependencies { compile 'io.realm:realm-android:0.80.0' }
Realmモデルを書く = テーブル定義を書く
public class User extends RealmObject { @PrimaryKey private long id; @Index private String name;
// Getter と Setter は省略 }
RealmRealm realm = Realm.getInstance(/* Context */); // Retrolambda realm.executeTransaction(_realm -> { User user = _realm.createObject(User.class); user.setId(1); user.setName("John Doe"); }); realm.close();
トランザクションの中でオブジェクトを作る
RealmRealm realm = Realm.getInstance(/* Context */); User user = realm.where(User.class) .equalTo("id", 1) .findFirst(); realm.close();
メソッドチェインでクエリを作ってオブジェクトを取り出すiOS 版では NSPredicate like な検索だが、Android ではクエリビルダ
Realm他の永続化機構との比較
RealmRealm SQLiteShared
Preferences
簡単XML KVS
遅い
面倒RDBMS速い
簡単NoSQL RDB
速い
いいとこ取り:)
RealmRealm ActiveAndroid
ORM (SQLite)ActiveRecord
遅い
簡単NoSQL RDB
速い
いいとこ取り:)
Realm初期化時間 [ms]
0
4000
8000
12000
16000
Realm ActiveAndroid
15,544 ms
5,054 ms
Insert 件数 10,000 件Nexus 4 / Android 5.0.1 JSON → Object
Realm実際に Realm を使うなら
Realm暗号化
Realmbyte[] key = new byte[64]; new SecureRandom().nextBytes(key); Realm realm = Realm.getInstance(/* Context */, key);
byte 型の配列を長さ 64 で作るSecureRandom#nextBytes を使って乱数バイトを取り出す
暗号化を使っても速度にそこまで影響しない!
Realm初期化時間 [ms]
0
4000
8000
12000
16000
Realm ActiveAndroid
15,544 ms
5,054 ms
Insert 件数 10,000 件Nexus 4 / Android 5.0.1 JSON → Object
↓暗号化を使った結果
Realmbyte[] key = new byte[64]; new SecureRandom().nextBytes(key); Realm realm = Realm.getInstance(/* Context */, key);
ドキュメントとサンプルの情報の整合性が取れていないKey の保存方法は提示されていない
ドキュメントは32 になっている
サンプルは単純なRandom になっている
どこかに保存したい
RealmKey を作ったらファイルにして保存する
Key ファイルがあれば読み出して byte 配列に格納する
byte[] key; File keyFile = context.getFileStreamPath(FILE_NAME); if (keyFile.exists()) { key = Files.readFromFile(keyFile, 64); } else { key = new byte[64]; new SecureRandom().nextBytes(key); Files.byteToFile(context, key, FILE_NAME); }
http://goo.gl/GIK2qXFiles →
RealmRealm オブジェクト
RealmRealm realm; try { realm = Realm.getInstance(/* Context */, key); } finally { if (realm != null) realm.close(); }
Realm を操作するときは Realm#getInstance を経由するRealm オブジェクトは使い終わったら close が必要である
Realmtry (Realm realm = Realm.getInstance(/* Context */, key)) { // do something }
Android 4.4 以上であれば try-with-resources が使えるでも、4.4 以上をターゲットにできるのは多分、来世
Realmpublic class MainActivity extends ActionBarActivity { private Realm mRealm; @Override protected void onCreate(Bundle savedInstanceState) { mRealm = Realm.getInstance(getApplicationContext()); } @Override protected void onDestroy() { super.onDestroy(); if (mRealm != null) mRealm.close(); } }
Activity の中であれば、インスタンス変数として保持してしまうonResume のタイミングで null チェックすると良いかも
onDestroy のタイミングで close する
Realmマルチスレッド
RealmRealm realm = Realm.getInstance(/* Context */, key); User user = realm.where(User.class) .equalTo("id", 1) .findFirst(); // Retrolambda new Thread(() -> { Log.d(TAG, user.getName()); }).start();
realm.close();
一見動きそうではある
Realm// Retrolambda new Thread(() -> { Realm realm = Realm.getInstance(/* Context */, key); User user = realm.where(User.class) .equalTo("id", 1) .findFirst();
Log.d(TAG, user.getName());
realm.close(); }).start();
Thread の中で Realm オブジェクトそのものから取得し直す必要があるRealm オブジェクトの close 忘れに要注意
Realm注意したいところ
Realmpublic class User extends RealmObject { @PrimaryKey private long id; @Index private String name;
// Getter と Setter は省略 }
モデルのフィールドに使える型は制約がある (詳細リンク)全てのフィールドは private かつ、Getter / Setter が必要であるequals, hashCode, toString も含めて、メソッドを設置できない
モデルの制約
Realm0.78
0.77
0.79
0.80
インメモリオブジェクトexecuteTransaction メソッド
暗号化機能
PrimaryKeyINSERT or Update (…orUpdate メソッド)
static フィールド Realm モデル
0.01 のアップデートが過激
Realmbyte[] key = new byte[64]; new SecureRandom().nextBytes(key); Realm realm = Realm.getInstance(/* Context */, key);
英語版のドキュメント = 最新 ≠ 正しい情報GitHub のサンプル ≠ 正しい情報
ドキュメントは32 になっている
サンプルは単純なRandom になっている
ドキュメントとサンプルコード
組み合わせ + 検証 + GitHub の changelog / Issues / Pull Request を読む
Realm最後に
Realm1. Realm は手軽に始められる 2. スタンドアロンアプリに最適 3. 非常に高速に動作する 4. まだ仕様や動作は注意が必要
Realm宣伝
RealmChatWork で働きませんか?
1. AndroidRealm, RxJava, RxAndroid
2. iOSReactiveCocoa, Mantle
3. WebScala, spray, DDD, ES6, React.js
下のキーワードにピンときた方、お声がけ or エントリを!