[英]Why I get ArrayIndexOutOfBoundsException when try delete objects in Realm?
There is such case, I need delete all objects from Realm and leave only last 10. 在这种情况下,我需要从Realm中删除所有对象,仅保留最后10个。
There is my method 有我的方法
private void invalidate() {
final int AVAILABLE_SIZE = 10;
final RealmResults<CardMainActivity> listToInvalidate = realmDB.where(CardMainActivity.class).findAll();
final int sizeOfList = listToInvalidate.size();
if (sizeOfList > AVAILABLE_SIZE) {
realmDB.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
for (int i = 0; i < sizeOfList - AVAILABLE_SIZE; i++) {
listToInvalidate.deleteFromRealm(i);
}
}
});
}
}
and there is error that I get 我有错误
FATAL EXCEPTION: main
Process: com.fittingroom.newtimezone, PID: 2438
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.fittingroom.newtimezone/com.fittingroom.newtimezone.view. activityMainNew.ActivityMainnew}: java.lang.ArrayIndexOutOfBoundsException: rowIndex > available rows: 12 > 12
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3253)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3349)
at android.app.ActivityThread.access$1100(ActivityThread.java:221)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.ArrayIndexOutOfBoundsException: rowIndex > available rows: 12 > 12
at io.realm.internal.TableView.nativeRemoveRow(Native Method)
at io.realm.internal.TableView.remove(TableView.java:410)
at io.realm.RealmResults.deleteFromRealm(RealmResults.java:295)
at com.fittingroom.newtimezone.tools.realmdb.RealmDB$1.execute(RealmDB.java:49)
at io.realm.Realm.executeTransaction(Realm.java:1304)
at com.fittingroom.newtimezone.tools.realmdb.RealmDB.invalidate(RealmDB.java:43)
at com.fittingroom.newtimezone.tools.realmdb.RealmDB.<init>(RealmDB.java:23)
at com.fittingroom.newtimezone.tools.realmdb.RealmDB.getInstance(RealmDB.java:28)
at com.fittingroom.newtimezone.view.activityMainNew.ControllerActivityMainnew.isDBContainsData(ControllerActivityMainnew.java:55)
But if I try delete my objects such way 但是如果我尝试以这种方式删除我的对象
private void invalidate() {
final int AVAILABLE_SIZE = 10;
final RealmResults<CardMainActivity> listToInvalidate = realmDB.where(CardMainActivity.class).findAll();
final int sizeOfList = listToInvalidate.size();
if (sizeOfList > AVAILABLE_SIZE) {
realmDB.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
for (int i = 0; i < sizeOfList - AVAILABLE_SIZE; i++) {
CardMainActivity card = listToInvalidate.get(i);
card.deleteFromRealm();
}
}
});
}
}
all works nice. 一切都很好。 But I need to use first approach
listToInvalidate.deleteFromRealm(i);
但是我需要使用第一种方法
listToInvalidate.deleteFromRealm(i);
, so ,所以
What am I doing wrong? 我究竟做错了什么?
RealmResults.deleteFromRealm() "also removes it from the collection." “ RealmResults.deleteFromRealm() ”还将其从集合中删除。“ So you are deleting 0, then the original 1 shifts into 0, then you delete index 1 with the incremented i.
因此,您要删除0,然后将原来的1移到0,然后删除i递增的索引1。 Let's try it with a list of size 8 and keeping 3:
让我们尝试使用大小为8的列表并保持3:
0 1 2 3 4 5 6 7, delete i = 0, continue if i < 8-3
1 2 3 4 5 6 7, delete i = 1, continue if i < 8-3
1 3 4 5 6 7, delete i = 2, continue if i < 8-3
1 3 5 6 7, delete i = 3, continue if i < 8-3
1 3 5 7, delete i = 4, Exception, there is no element 4
What you could do is delete index 0 each time. 您可以做的就是每次删除索引0。 Your second sample does not delete it from the RealmResults collection so you don't have this problem.
您的第二个示例不会将其从RealmResults集合中删除,因此您不会遇到此问题。
I would suspect that when you are deleting from the list that you are looping through, the size of that list is shrinking on each iteration. 我怀疑当您从要遍历的列表中删除时,该列表的大小在每次迭代时都会缩小。 So, your loop quickly gets to a point where the index is out of bounds.
因此,您的循环很快就会到达索引超出范围的地步。 (John C does a great job of explaining this in his answer)
(John C在回答这个问题上做得很出色)
As for a solution, I would suggest looping through and 'marking' entries for invalidation, and THEN going through and removing the marked items. 至于解决方案,我建议循环遍历并“标记”无效的条目,然后遍历并删除标记的项目。 This way, you don't have to rely on the index (which is changing as you invalidate items).
这样,您不必依赖索引(随着使项目无效,索引会不断变化)。
Let me know if this makes sense, and I'll try to clarify what I mean if it does not. 让我知道这是否有意义,如果没有,我会尝试澄清我的意思。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.