2017-03-01 68 views
0

有这样的情况下,我需要境界删除所有对象,只留下最后10为什么我在尝试删除Realm中的对象时遇到ArrayIndexOutOfBoundsException?

有我的方法

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

你使用的是什么版本? – EpicPandaForce

+0

@EpicPandaForce领域2.3.1 –

回答

3

RealmResults.deleteFromRealm()“也将其从集合中删除”。所以你删除0,然后原来的1变成0,然后删除索引1,增加i。让我们尝试一个大小为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集合中删除它,所以你没有这个问题。

+0

这正是我在回答我的问题时所说的,很好的工作是通过这个例子来阐明的。 – ryguy

+1

@ryguy,抱歉没有看到你的答案,当我发布这个或者我会给一些信用:-) –

+1

'你的第二个样本不会从RealmResults集合中删除它,所以你没有这个问题。实际上,我认为这可能是第二个例子将与Realm Java 3.0.0中断的少数情况之一,所以他应该在迭代之前使用'createSnapshot()'。 – EpicPandaForce

1

我怀疑当你从列表中删除你正在循环时,这个列表的大小在每次迭代时都会缩小。所以,你的循环很快就会到达索引超出范围的地步。 (约翰C在他的回答中做了很好的解释)

至于解决方案,我会建议通过循环和'标记'条目进行失效,然后通过并删除标记的项目。这样,您不必依靠索引(随着您使项目无效而改变)。

让我知道这是否合理,我会尽力澄清我的意思,如果没有。

相关问题