有这种情况,我需要删除Realm中的所有对象,并且只留下最后10个。
有我的方法
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);
}
}
});
}
}
我有错误
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)
但如果我尝试删除我的对象
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();
}
}
});
}
}
一切都很好。但我需要使用第一种方法listToInvalidate.deleteFromRealm(i);
,所以
我做错了什么?
答案 0 :(得分:3)
RealmResults.deleteFromRealm()“也会从集合中删除它。”因此,您正在删除0,然后原始1转换为0,然后您使用递增的i删除索引1。让我们尝试使用大小为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
您可以做的是每次删除索引0。您的第二个示例不会将其从RealmResults集合中删除,因此您不会遇到此问题。
答案 1 :(得分:1)
我怀疑当你从列表中删除你正在循环时,该列表的大小在每次迭代时都在缩小。因此,您的循环很快就会达到索引超出范围的程度。 (John C在他的回答中做了很好的解释)
至于解决方案,我建议循环并“标记”无效的条目,然后通过并删除标记的项目。这样,您就不必依赖索引(当您使项目无效时,索引会发生变化)。
让我知道这是否有意义,如果没有,我会尽量澄清我的意思。