3

It may be a red herring, but my app is full of UI-less task fragments to perform most network operations and work around the activity lifecycle. An example of this type of architecture is described here. https://stackoverflow.com/a/12303649/2662474

On new Google Pixel and Nexus phones running Oreo 8.0, the app has started crashing on resume of many different activities in a way that is very difficult to debug and seems like a low level Android bug that was introduced. It is not happening on any previous OS versions.

Fatal Exception: java.lang.RuntimeException: Unable to resume activity {com.mycompany.shop/com.mycompany.shop.activity.MainNavActivity}: java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3645)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3685)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1643)
       at android.os.Handler.dispatchMessage(Handler.java:105)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6541)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
       at java.util.ArrayList.get(ArrayList.java:437)
       at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1610)
       at android.app.FragmentManagerImpl.dispatchMoveToState(FragmentManager.java:3035)
       at android.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:3001)
       at android.app.FragmentController.dispatchResume(FragmentController.java:200)
       at android.app.Activity.performResume(Activity.java:7100)
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3620)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3685)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1643)
       at android.os.Handler.dispatchMessage(Handler.java:105)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6541)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

Please help!

joseph
  • 1,165
  • 1
  • 7
  • 16

2 Answers2

2

Your error is occurring in the method moveToState() of the nested class FragmentManagerImpl in FragmentManager. The specific code that is causing the erorr is Fragment f = mAdded.get(i) in the following lines:

final int numAdded = mAdded.size();
for (int i = 0; i < numAdded; i++) {
    Fragment f = mAdded.get(i); // [causing the error]
    moveFragmentToExpectedState(f);
    if (f.mLoaderManager != null) {
        loadersRunning |= f.mLoaderManager.hasRunningLoaders();
    }
}

mAdded is a list of added fragment and is defined as:

ArrayList<Fragment> mAdded;

When the error occurs, i == 3 and the size of the mAdded Arraylist is something less than that. (Error line: "java.lang.IndexOutOfBoundsException: Index: 3, Size: 3") For this to occur, a fragment must have been removed from mAdded somewhere within this for-loop, specifically somewhere in the call chain starting with moveFragmentToExpectedState().

You mention that your app is "work[ing] around the activity lifecycle." Maybe you are getting a fragment into an unexpected state according the Oreo 8.0. I suggest that you put your app into the debugger and set a breakpoint in this for loop. You can then try to track down where the Arraylist mAdded is being changed. That should at least point you in the right direction for the solution.

btw, the source code for API 26 has been released. It can help you in debugging.


Update: From looking at the source, that area of FragmentManger in API 26 has received substantial work from the version in API 25. You may want to take azizbekian's suggestion and move to android.support.v4.app.Fragment. The support version seems to be more in line with API 25 than API 26. This could be a stop-gap measure until you can figure out the root cause.

Regarding your current implementation, I would look for anything that would remove or detach a fragment during the onResume() processing, especially if it is done off the UI thread and maybe in a non thread-safe manner. Look for anything that invoke, directly or indirectly, removeFragment() or detachFragment() of FragmentManager since these seem to be the only places where fragments are removed from mAdded.

Cheticamp
  • 61,413
  • 10
  • 78
  • 131
1

Did you try this?: Nesting fragments inside a viewpager fragment throws IndexOutOfBoundsException

You may using getSupportFragmentManager() to call remove().
So, change getSupportFragmentManager() to YourFragment.this.getFragmentManager()

Linked answer said:

Change

getActivity().getSupportFragmentManager().beginTransaction().remove(instance).commit();

to

ThisFragment.this.getFragmentManager().beginTransaction().remove(instance).commit();
Stanley Ko
  • 3,383
  • 3
  • 34
  • 60
  • I am using taskfragments that do not have any view attached. I will try your suggestion to see if it makes any sense... – joseph Oct 15 '17 at 06:21