简体   繁体   中英

ArrayIndexOutOfBoundsException when manipulating ArrayAdapter

Long story short: I have a listView with a customAdapter (called MathAdapter). This Adapter handles an ArrayList of type CalculationModel. By default there are ~15 CalculationModels in my List, however, under special conditions, i have to delete about 6 of them.

Since i am pretty new to Android Development (I'm coming from iOS), my first basic question is:

Where would one normally manipulate the ListData? In my case, a fragment initializes the adapter and passes a list of my data. During the lifetime of my app, i manipulate this list and call notifiyDataSetChanged. Everything works as expected, and I'm able to remove or add 1 CalculationModel at a time without any problems.

There is also no problem when deleting 6 CalculationModels, works fine too. The App crashes when i try to reinsert them with the following ErrorLog:

04-27 07:48:59.194 1766-1766/com.example.test E/AndroidRuntime: FATAL EXCEPTION: main
   Process: com.example.test, PID: 1766
   java.lang.ArrayIndexOutOfBoundsException: length=11; index=11
       at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:8271)
       at android.widget.ListView.layoutChildren(ListView.java:1600)
       at android.widget.AbsListView.onLayout(AbsListView.java:2528)
       at android.view.View.layout(View.java:15655)
       at android.view.ViewGroup.layout(ViewGroup.java:4856)
       at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
       at android.view.View.layout(View.java:15655)
       at android.view.ViewGroup.layout(ViewGroup.java:4856)
       at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
       at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
       at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
       at android.view.View.layout(View.java:15655)
       at android.view.ViewGroup.layout(ViewGroup.java:4856)
       at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
       at android.view.View.layout(View.java:15655)
       at android.view.ViewGroup.layout(ViewGroup.java:4856)
       at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
       at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
       at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
       at android.view.View.layout(View.java:15655)
       at android.view.ViewGroup.layout(ViewGroup.java:4856)
       at com.example.test.TouchDisableView.onLayout(TouchDisableView.java:57)
       at android.view.View.layout(View.java:15655)
       at android.view.ViewGroup.layout(ViewGroup.java:4856)
       at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
       at android.view.View.layout(View.java:15655)
       at android.view.ViewGroup.layout(ViewGroup.java:4856)
       at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
       at android.view.View.layout(View.java:15655)
       at android.view.ViewGroup.layout(ViewGroup.java:4856)
       at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2284)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2004)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1236)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6471)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
       at android.view.Choreographer.doCallbacks(Choreographer.java:603)
       at android.view.Choreographer.doFrame(Choreographer.java:573)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
       at android.os.Handler.handleCallback(Handler.java:733)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:157)
       at android.app.ActivityThread.main(ActivityThread.java:5356)
       at java.lang.reflect.Method.invokeNative(Native Method)
       at java.lang.reflect.Method.invoke(Method.java:515)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
       at dalvik.system.NativeStart.main(Native Method)

To make it clear, im not new to Java, and i see that ArrayIndexOutOfBounds is the problem, but i have no clue where this happens, since my list and the item count in the adapter are higher than 11 (14 as expected)

Code:

    List<CalculationModel> data;
    List<CalculationModel> backupData = new ArrayList<>();    

@Override
public void onResume() {
    if (mathApp.isCleanPhase) {
        removeNonClearData();
    } else {
        addNonClearData();
    }

    adapter.notifyDataSetChanged();

    super.onResume();
}


    public void removeNonClearData() {
    if (backupData.size() > 0) return;

    for (int i = 0; i < data.size(); i++) {
        CalculationModel tmp = data.get(i);

        String sName = tmp.getSName();

        if (sName.equals("r") || sName.equals("wv") || sName.equals("qv") || sName.equals("tw") || sName.equals("ti") || sName.equals("h") || sName.equals("rs")) {
            backupData.add(data.remove(i));
            i--;
        }
    }

    adapter.itemCount = data.size();
}

public void addNonClearData() {
    if (backupData.size() == 0) return;

    for (int i = 0; i < backupData.size(); i++) {
        //'r' is a default parameter, which shall be in row 6
        if (backupData.get(i).getSName().equals("r")) data.add(5, backupData.remove(i));
        else data.add(backupData.remove(i));
    }

    adapter.itemCount = data.size();

    print(data.size());
}

EDIT: Forgot to mention, the data gets basically loaded the way i want it to, but the app crashes when im scrolling back up again in my list. All the data is in the list i want to see there, but when scrolling up, --> Crash.

Like mentioned, i just don't understand where this Error comes from, since the log gives no information about it...

when you are removing data from array call notifyDataSetChanged(); 

After a long time (basically the last 2 days) of frustration and confusion I finally managed to understand how this Adapters for ListViews work (At least i hope).

As described in the question i have the following setup: A Fragment holding a list of data, and the adapter, which gets this list of data at initialization.

Now there are two different behaviors of the adapter when manipulating data.

If one just edits one of the objects in the list (eg i want to change param "value" of my CalculationModel on position 4, everything works fine and changes are accepted with notifyDataSetChanged().

If one deletes a complete object from the list, notifyDataSetChanged() is also working and doing the expected job.

But, if one was about to add a new object to the list, (or in my case, re-insert the removed one) it is NECESSARY to recreate the whole adapter, since notifyDataSetChanged() has no effect anymore.

Thanks for the help, i may not have made it without the input in the comments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM