1. Qiita
  2. 投稿
  3. Android

Realm for Android

  • 189
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

こんにちは @wasabeef_jpです。

Realm for Androidの話をしたいと思います。

realm.png

引用:http://wasabeef.jp/realm-for-android/

Realmとは

"Realm is a mobile database: a replacement for SQLite & Core Data
Realm can save you thousands of lines of code & weeks of work,
and lets you craft amazing new user experiences."

SQLite & Core Dataを置き換えるために作られた Mobile向けのDataBase
元々、iOS向けに作られていましたが、C++で書いているので、Androidにも対応しています。

SQLiteのORMとの速度比較
benchmarks-android.001.png

benchmarks-android.002.png

benchmarks-android.003.png

どうやら速いらしい。

Setup

公式にjarが置いてありますが、Gradleであれば以下のようにします

// build.gradle
compile 'io.realm:realm-android:0.71.+'

Models

ActiveAndroidとかSugarORMと似たように、RealmObjectを継承しておきます。

public class User extends RealmObject {
    private String          name;
    private int             age;

    @Ignore
    private int             sessionId;

    // Standard getters & setters generated by your IDE…
    public String getName() { return name; }
    public void   setName(String name) { this.name = name; }
    public int    getAge() { return age; }
    public void   setAge(int age) { this.age = age; }
    public int    getSessionId() { return sessionId; }
    public void   setSessionId(int sessionId) { 
        this.sessionId = sessionId;
    }
}

Writes

Transactionの開始と終了は必須となります。
先ほど、定義したModelをcreateObjectに渡して
インスタンスを作ってもらい、それに対してデータの設定を行うだけとなります。

// Obtain a Realm instance
Realm realm = Realm.getInstance(this, "wasabeef.realm");

realm.beginTransaction();

// Create a new object
User user = realm.createObject(User.class);
user.setName("Wasabeef");
user.setEmail("chip@wasabeef.jp");

realm.commitTransaction();

Queries

メソッドチェインにも対応していて、とてもシンプルに書けます。
ただ、SQLiteではないので、SQL文を使うことは出来ません。

// Build the query looking at all users:
RealmQuery<User> query = realm.where(User.class);

// Add query conditions:
query.equalTo("name", "Wasabeef");
query.or().equalTo("name", "Chip");
// Execute the query:
RealmResults<User> resultAll = query.findAll();

// Or alternatively do the same all at once (the "Fluent interface"):
RealmResults<User> result = 
                       realm.where(User.class)
                            .equalTo("name", "Wasabeef")
                            .or()
                            .equalTo("name", "Chip")
                            .findAll();

Sorting

Asc, Descにも対応してます。

// Query
RealmResults<User> result = realm.where(User.class).findAll();

// Asc
RealmResults<User> sortedAscending  = result.sort("age");

// Desc
RealmResults<User> sortedDescending = 
        result.sort("age", RealmResults.SORT_ORDER_DECENDING);

Deletion

// All changes to data must happen in a transaction
realm.beginTransaction();

// remove single match
result.remove(0);
result.removeLast();

// Delete all matches
result.clear();

realm.commitTransaction()

RealmObject & RealmResults

The only rule to using Realm across threads is to remember that Realm, RealmObject or RealmResults instances cannot be passed across threads. When you want to access the same data from different threads, you should simply obtain a separate Realm instance for each thread (i.e. Realm.getInstance(this) or its cousins) and get your objects through a RealmQuery. The objects will map to the same data on disk, and will be readable & writeable from any thread!

Thread間での受け渡しの想定はしてないので
Realm.getInstance()とRealmQuery()を通して再取得する必要がある

Migration

Libraryで吸収しきれて無いので、結構めんどうくさいです。

public class Migration implements RealmMigration {
    @Override
    public long execute(Realm realm, long version) {

        // Migrate from version 0 to version 1
        if (version == 0) {
            // 自分で、Tableの再構築を行う必要がある
            // 省略
            version++;
        }
    }
}

抱えてる問題点 (Latest 0.71.0)

  • ModlesにSetter/Getterしか書けない

 Debugなどで使いたいので、せめてtoString()くらいは書きたい

Error:(12, 19) エラー: Only getters and setters should be defined in model classes
注意:Processing class Person
  • EnumはSupportしてない

 プロパティにEnumがあると、Buidが通らない

Error:(21, 8) エラー: Type io.realm.examples.intro.model.Cat.HogeType of field type is not supported
  • RealmObjectをGSONでSerialize出来ない
 java.lang.StackOverflowError
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:376)
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:381)
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:376)
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:381)
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:376)
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:381)
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:376)
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:381)
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:376)
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:381)
            at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:376)
  • Migrationがイケてない

本当にイケてない、いや他のORMとかの考え方が綺麗なだけのかも。

Realm Browser

Realm DataBaseをGUIで閲覧・編集できるツールも用意されてます。

browser.png

雑感

Realmは、SQLiteを使っていません。
独自にFormatで、DataBaseを作成してます。

特に保存先を指定しなければ、以下のFile DirにRealm Formatで保存されます。
/data/data/パッケージ名/files/

まだVersionも1.xに行っていないので、今後に期待したいと思ってます。