Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IndexOutOfBoundsException after repopulating ArrayList (Marshmallow only)

My setup is as follows: inside my onCreate I initialize an ArrayList as follows:

textList = new ArrayList<HashMap<String, String>>();

// unrelated code ...

if (isConnected()) {
    new DisplayTextTask().execute(sectionId);
}

and the AsyncTask fetches text via HttpURLConnection(), parses the json using JsonReader, and adds each line of text to the textList (all of this happens inside the AsyncTask's doInBackground. I have a custom Adapter that displays the strings in textList.

I also have a function gotoNextSection() that gets triggered when the user wants to navigate to the next page, where I do something like:

gotoNextSection() {
    if (isConnected()) {
        new DisplayTextTask().execute(sectionId+1);
    }
}

However, since I don't want the stale text from the previous page to remain on screen, I do the following in my AsyncTask:

private class DisplayTextTask extends AsyncTask<String, Void, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        textList.clear();
    }

    @Override
    protected String doInBackground(String... urls) {
        // json parsing is called in getData()
        try {
            return getData(urls[0]);
        } catch (IOException e) {
            return "Could not load text";
        }
    }

so that the arrayList is empty and ready to be repopulated. All of this works fine in all other supported Android versions but when I tried it in a Marshmallow emulator gotoNextSection() results in an IndexOutOfBoundsException. This occurs after the new content is added to the freshly cleared arrayList (verified via logging), so I don't think it's a race condition. Note that not clearing the list prevents the exception, and since this is the only ArrayList used in the Activity I'm positive that .clear() is the problem. I've tried nulling and reinitializing it before launching the AsyncTask as an alternative as well, to no avail. Again, this happens exclusively on Android 6.0. Thoughts?

EDIT: Here's the logcat stacktrace. Note that the size of index that it's attempting to access and where in the code this occurs is irrelevant because I've tried to log the ArrayList after the task is executed in gotoNextSection and it just gives me an exception for whatever index I've tried to access in the log.

java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
        at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
        at java.util.ArrayList.get(ArrayList.java:308)
        at android.widget.HeaderViewListAdapter.isEnabled(HeaderViewListAdapter.java:164)
        at android.widget.ListView.dispatchDraw(ListView.java:3329)
        at android.view.View.draw(View.java:16181)
        at android.widget.AbsListView.draw(AbsListView.java:4142)
        at android.view.View.updateDisplayListIfDirty(View.java:15174)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
        at android.view.View.updateDisplayListIfDirty(View.java:15134)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
        at android.view.View.updateDisplayListIfDirty(View.java:15134)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
        at android.view.View.updateDisplayListIfDirty(View.java:15134)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
        at android.view.View.updateDisplayListIfDirty(View.java:15134)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
        at android.view.View.updateDisplayListIfDirty(View.java:15134)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
        at android.view.View.updateDisplayListIfDirty(View.java:15134)
        at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281)
        at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287)
        at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322)
        at android.view.ViewRootImpl.draw(ViewRootImpl.java:2615)
        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2434)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2067)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
        at android.view.Choreographer.doCallbacks(Choreographer.java:670)
        at android.view.Choreographer.doFrame(Choreographer.java:606)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
like image 933
irvanjitsingh Avatar asked Aug 24 '15 07:08

irvanjitsingh


1 Answers

Solved: I ended up having to disconnect the adapter from the ListView before calling clear and reconnecting it afterwards in postExecute(), I'm guessing Marshmallow is more strict about data binding

like image 54
irvanjitsingh Avatar answered Nov 10 '22 19:11

irvanjitsingh