2017-03-01 40 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在他的回答中做了很好的解釋)

至於解決方案,我會建議通過循環和'標記'條目進行失效,然後通過並刪除標記的項目。這樣,您不必依靠索引(隨着您使項目無效而改變)。

讓我知道這是否合理,我會盡力澄清我的意思,如果沒有。

相關問題