FragmentManager IndexOutOfBoundsException无法恢复活动崩溃

时间:2017-09-26 21:37:03

标签: android crash android-lifecycle android-8.0-oreo

它可能是一个红色的鲱鱼,但我的应用程序充满了无UI的任务片段,可以执行大多数网络操作并解决活动生命周期。这里描述了这种架构的一个例子。 https://stackoverflow.com/a/12303649/2662474

在运行Oreo 8.0的新款Google Pixel和Nexus手机上,应用程序已经开始以很难调试的方式恢复许多不同的活动,并且看起来像是引入的低级Android错误。它不会发生在任何以前的操作系统版本上。

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)

请帮忙!

2 个答案:

答案 0 :(得分:2)

您的错误发生在moveToState()中嵌套类FragmentManagerImpl的方法FragmentManager中。导致erorr的特定代码在以下行中为Fragment f = mAdded.get(i)

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是添加片段的列表,定义为:

ArrayList<Fragment> mAdded;

发生错误时,i == 3和mAdded Arraylist的大小小于此值。 (错误行:&#34; java.lang.IndexOutOfBoundsException:索引:3,大小:3&#34;)为此,必须在此for循环中的某个位置从mAdded删除片段,特别是以moveFragmentToExpectedState()开头的调用链中的某个位置。

您提到您的应用是围绕活动生命周期工作的。&#34;根据Oreo 8.0,你可能会将片段变成意想不到的状态。我建议您将应用程序放入调试器并在此for循环中设置断点。然后,您可以尝试跟踪Arraylist mAdded的更改位置。这至少应该为您找到解决方案的正确方向。

顺便说一句,API 26的源代码已经发布。它可以帮助您进行调试。

更新:通过查看来源,API 26中FragmentManger的某个区域已经从API 25中的版本中获得了大量工作。您可能想要使用azizbekian&#39; s建议并移至android.support.v4.app.Fragment。支持版本似乎更符合API 25而不是API 26.这可能是一个权宜之计,直到你找出根本原因。

关于您当前的实现,我会寻找在onResume()处理期间删除或分离片段的任何内容,特别是如果它是在UI线程之外完成并且可能是非线程安全的方式。查找直接或间接调用removeFragment()的{​​{1}}或detachFragment()的任何内容,因为这些似乎是唯一从FragmentManager中删除片段的地方。

答案 1 :(得分:1)

你试过这个吗?:Nesting fragments inside a viewpager fragment throws IndexOutOfBoundsException

您可以使用getSupportFragmentManager()来调用remove() 因此,将getSupportFragmentManager()更改为YourFragment.this.getFragmentManager()

链接答案说:

变化

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

ThisFragment.this.getFragmentManager().beginTransaction().remove(instance).commit();