java.lang.IllegalStateException:键f1:index 3不再存在片段

Ixx*_*Ixx 47 android android-fragments

我想了解此异常以实现正确的修复.

概述:

有一个ViewPager,它使用FragmentStatePagerAdapter通过getItem和实例化2个片段MyFragmentClass.newInstance(...).

Adapter的getItem看起来像这样:

@Override
public Fragment getItem(int position) {
    Fragment fragment = null;

    switch(position) {
        case 0:
            fragment = MyFragment2.newInstance(par1);
            break;
        case 1:
            fragment = MyFragment2.newInstance(par2, par3);
            break;
    }
    return fragment;
}
Run Code Online (Sandbox Code Playgroud)

问题:

当活动被销毁并再次创建时,适配器再次被实例化,片段再次创建MyFragmentClass.newInstance(...)...但在此行上:

pager.setAdapter(adapter);

我得到了提到的例外.

我查看了抛出异常的源代码,它是这样的:

@Override
public Fragment getFragment(Bundle bundle, String key) {
    int index = bundle.getInt(key, -1);
    if (index == -1) {
        return null;
    }
    if (index >= mActive.size()) {
        throw new IllegalStateException("Fragement no longer exists for key "
                + key + ": index " + index);
    }
    Fragment f = mActive.get(index);
    if (f == null) {
        throw new IllegalStateException("Fragement no longer exists for key "
                + key + ": index " + index);
    }
    return f;
}
Run Code Online (Sandbox Code Playgroud)

因此,在那里传递一个bundle,其中一些状态引用了我的旧片段,但是这与当前的state(mActive)不对应,并且抛出了异常.

我不明白这背后的想法是什么,或者我实际上应该以哪种方式实例化片段......所以我不知道如何解决.

我还尝试了一些其他上下文中的技巧:

pager.setOffscreenPageLimit(1);

为了避免片段在屏幕外被破坏(在2页viewpager的情况下,虽然不知道它是否适用于状态适配器).但似乎没有相关性,至少,它没有帮助,仍然得到相同的例外.

我现在所做的是在线路周围放置一个try catch块,好吧,然后我得到空白页而不是崩溃盒,也不好.

Mik*_*eps 53

这可能有所帮助 -

@Override
public Parcelable saveState() {
    return null;
}
Run Code Online (Sandbox Code Playgroud)

添加上面的行FragmentStatePagerAdapter.

  • 如果你避免使用`saveState()`,你不再需要使用`FragmentStatePagerAdapter`.然后你只需要使用`FragmentPagerAdapter`来工作 (5认同)
  • 这非常适合处理后栈中的分页适配器.谢谢! (3认同)
  • 谢谢你,它的工作就像一个魅力 (2认同)
  • @Lennon`FragmentPagerAdapter`不使用`saveState()`因为整个片段都保留在内存中.如果你想避免这种行为,你可以使用只能保存状态的`FragmentStatePagerAdapter`.如果您根本不想保存任何内容,则使用`FragmentStatepagerAdapter`而不保存状态; 它自动不会将"片段"保存在内存中. (2认同)

tad*_*tad 23

如果您不希望片段在屏幕外时被回收,那么您应该使用FragmentPagerAdapter而不是FragmentStatePagerAdapter.

  • `FragmentPagerAdapter`在访问时将每个片段加载到内存中.`FragmentStatePagerAdapter`在超过`offscreenPageLimit`参数时释放对片段的引用. (2认同)

Vic*_*cky 9

问题详细信息

默认情况下,FragmentStatePagerAdapter将保存和还原ViewPager的状态。在恢复时,如果片段实例由于某种原因被杀死,则FragmentManger将抛出此异常。

解决方案:

要解决此问题,需要覆盖我们的FragmentStatePagerAdapter中的restoreState方法,并放置try catch块。它将防止崩溃,并且在正常情况下还将保留viewpager的片段状态。

@Override
public void restoreState(Parcelable state, ClassLoader loader) {
    try {
        super.restoreState(state, loader);
    } catch (Exception e) {
        Log.e("TAG", "Error Restore State of Fragment : " + e.getMessage(), e);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:我们可以使用FragmentPagerAdapter或Override saveState()并返回null也可以解决此问题,但在正常情况下viewpager不会保留其状态。

  • 无法覆盖,它被设置为最终的:( (2认同)

nab*_*eel 9

如果您使用的是 ViewPager2,则在 ViewPager2 对象上使用此方法

viewPager2.setSaveEnabled(false);
Run Code Online (Sandbox Code Playgroud)