Edited at

Realm for Javaでupdate操作の時に注意すべきこと

More than 1 year has passed since last update.

2017/06/16追記

いつの間にかこのような場合の正しい方法が公式docに記載されてました。

今後はこっちを参照してもらうほうが良いです。

https://realm.io/docs/java/latest/#iterations--snapshots

ただし、何らかの理由で、新しいバージョンが使えない人たち向けにこの情報は残しておきます。


古い情報だよ!

Realmを使っていて、ある条件にヒットするデータを探して、検索に使用した値をアップデートしたいことってよくあると思います。

具体的に言うとこういうコードの場合

mRealm.beginTransaction();

RealmResults<Obj> results = mRealm.where(Obj.class).equalTo("status", 0).findAll();
int resultCount = results.size();

for (int count = 0; count < resultCount; ++count) {
Obj obj = results.get(count);
obj.setStatus(1);
}
mRealm.commitTransaction();

これ、行けそうに見えて、実際に実行すると、java.lang.ArrayIndexOutOfBoundsExceptionが発生してひどく悲しい気分になれます。

某所で質問したところ、最初の検索条件に使用しているパラメーターを途中で書き換えているためにRealmResults<Obj>自体が更新され配列が減っているために起こっているとのこと。

なので正解のコードはこんな感じになるらしい。

mRealm.beginTransaction();

RealmResults<Obj> results = mRealm.where(Obj.class).equalTo("status", 0).findAll();

while(results.size() > 0){
Obj obj = results.get(0);
obj.setStatus(1);
}
mRealm.commitTransaction();

iteratorを使えという話はこんなことになっているので無理ということで。

ConcurrentModificationException when using iterators methods #640

https://github.com/realm/realm-java/issues/640

自動更新を止めるAPI追加の方向で動いているらしい

https://github.com/realm/realm-java/commits/stk/waitforchange