9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Realmでデータを保存する時の注意点 (Managed / Unmanagedの区別, copyToRealm()をいつ使うか)

Last updated at Posted at 2019-02-24

#はじめに
Realmを使い始めてまだ間もない頃、copyToRealm()の役割を理解しないままコードを書いていたせいで、バグを連発してしまいました。これは、そのときの自分に読ませたい記事です。

教訓: ManagedObjectとUnmanagedObjectの違いを理解してコードを書こう

Realmのオブジェクトには ManagedObjectUnmanagedObject の2パターンがあります。
これに関して、Realmの公式ドキュメント(Realm Java 5.9.1)には、次のような説明があります。

Instances of Realm objects can be either managed or unmanaged.

Managed objects are persisted in Realm, are always up to date and thread confined. They are generally more lightweight than the unmanaged version as they take up less space on the Java heap.
Unmanaged objects are just like ordinary Java objects, they are not persisted and they will not be updated automatically. They can be moved freely across threads.
It is possible to convert between the two states using Realm.copyToRealm and Realm.copyFromRealm.

上記をGoogle翻訳にかけたあと、微修正したものがこちらです。

Realmオブジェクトのインスタンスは、Managed(=管理対象)またはUnmanaged(=管理対象外)のどちらでも構いません。
ManagedObjectはRealmに永続化され、常に最新の状態に保たれ、スレッドは制限されます。これらはJavaヒープ上の占有スペースが少ないので、一般的にUnmanagedObjectよりも軽量です。
UnmanagedObjectは、通常のJavaオブジェクトとまったく同じです。永続化されていないため、自動的に更新されることはありません。 これらはスレッド間で自由に移動できます。
Realm.copyToRealmとRealm.copyFromRealmを使用することで、2つの状態を切り替えることができます。

ポイントは、
UnmanagedObject の値は自動更新されないため、適宜Realm.copyToRealm()を使う必要がある、ということです。

実装例: ToDoオブジェクトの保存 (2通り)

例えば、次のようなクラスをRealmで管理したいとします。


public class ToDo extends RealmObject{
    // タイトル
    public String title;
    // 日付
    public String updateDate;
    // 内容
    public String content;
    // チェックボックスがチェックされているか
    public boolean isChecked;    
}

このToDoクラスのオブジェクトを最初に実装するときは、ManagedObjectUnmanagedObject のどちらでも構いません。

                //  ManagedObjectとして実装
                ToDo todo = realm.createObject(ToDo.class);

                //  UnmanagedObjectとして実装
                ToDo todo = new ToDo();

なぜなら、先ほどの公式ドキュメントの引用文中にもあったように、処理の途中でUnmanagedObjectManagedObjectに変更したいときはRealm.copyToRealm()を使うことで解決でき、ManagedObjectUnmanagedObjectに変更したいときはRealm.copyFromRealm()を使うことで解決できるからです。

ただし、大抵のRealm入門記事ではManagedObjectとして実装されています。(自分調べ)

ToDoオブジェクトの保存メソッド

オブジェクトの持つ値を保存するときは、そのオブジェクトがManagedObject なのか UnmanagedObject なのかを区別して処理を書く必要があります。

例として、ToDoオブジェクトの保存メソッドsave()を用意しました。

まずは、次の枠組みを見てください。

saveメソッドの枠組み
    public void save(final String title, final String updateDate, final String content){
        realm.executeTransaction(new Realm.Transaction(){
            @Override
            public void execute(Realm bgRealm){

                // ここに、値を保存するための処理を書く。

            }
        });
    }

この枠組みの中に、オブジェクトの状態に合わせた処理を書く必要があります。

ManagedObjectを保存するとき

ManagedObjectの値は自動で更新されるため、通常のJavaオブジェクトと同じような処理で構いません。

枠組みの中の処理
                ToDo todo = realm.createObject(ToDo.class);
                // 保存したい値を代入
                todo.title = title;
                todo.updateDate = updateDate;
                todo.content = content;

UnmanagedObjectを保存するとき

UnmanagedObjectの値は自動で更新されないため、最後にRealm.copyToRealm()を使う必要があります。

枠組みの中の処理

                ToDo todo = new ToDo();
                // 保存したい値を代入
                todo.title = title;
                todo.updateDate = updateDate;
                todo.content = content;
                // UnmanagedObjectからManagedObjectへと変更してRealmへコピー
                realm.copyToRealm(todo);

一言まとめ

Realmを使うときは、オブジェクトがManagedなのかUnmanagedなのかに注意してコードを書きましょう。

9
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?