FragmentStatePagerAdapter IllegalStateException:<MyFragment>当前不在FragmentManager中

我在一些使用FragmentStatePagerAdapter的活动的onResume()函数中得到了这个结果。 当使用设备的后退button。 不总是。 不可重现。

我正在使用支持包v4,上次修订(8)。

已经用谷歌search,没有find有用的答案成功。

查看源代码,在这里抛出:FragmentManager.java

@Override public void putFragment(Bundle bundle, String key, Fragment fragment) { if (fragment.mIndex < 0) { throw new IllegalStateException("Fragment " + fragment + " is not currently in the FragmentManager"); } bundle.putInt(key, fragment.mIndex); } 

但为什么片段索引<0呢?

实例化碎片的代码:

 @Override public Fragment getItem(int position) { Fragment fragment = null; switch(position) { case 0: fragment = MyFragment.newInstance(param1); break; case 1: fragment = MyFragment2.newInstance(param2, param3); break; } return fragment; } @Override public int getCount() { return 2; } 

我也无法通过源代码进行debugging,因为支持包不允许我附加源代码,出于某种原因…但这是一个不同的问题…

Solutions Collecting From Web of "FragmentStatePagerAdapter IllegalStateException:<MyFragment>当前不在FragmentManager中"

如果你的ViewPager是在一个片段(而不是一个活动)内:

mViewPager.setAdapter(new MyFragmentStatePagerAdapter(get Child FragmentManager()));

我在这里有同样的错误,但另一个原因。

在我的情况下,我已经在我的FragmentStatePagerAdapter覆盖getItemPosition。 我的意识是要返回的位置,如果该项目存在,或POSITION_NONE,如果它不存在了。

那么,我的问题是,当我的集合空了,我返回POSITION_NONE。 这一切都打破了。

我的修复是当我有一个空集合返回POSITION_UNCHANGED。

希望它可以帮助别人。

了解这个bug的两个关键是:

  1. 有时会发生。
  2. 它发生在onResume()

鉴于这些信息, ViewPager可能不会保留您的Fragment的状态。 如果您直接从Activity中操作Fragment ,则可能是页外Fragment被破坏, Activity正在尝试操作null片段。 即使不在当前屏幕中,也要保留Fragment的状态,修复非常简单:

 private static final int NUM_ITEMS = 2; ViewPager mPager = /** instantiate viewpager **/; mPager.setOffscreenPageLimit(NUM_ITEMS-1); 

你可以在这里读到它:

ViewPager随着时间的推移碎片被破坏?

明白了,原因是,我每次都在onResume()中使用适配器。

如果我仅在适配器的生命周期中实例化适配器一次,则不会再发生这种情况。

这个exception意味着你试图将一个片段附加到一个不再是正确的状态的活动来附加这些片段。 这意味着,无论何时我们尝试附加片段( 特别是通过asynchronous调用 ),在附加片段时,有人按下后退button的可能性很小,并且活动在合并中被破坏。 这只是一个竞争条件,并不总是可重复的,并不总是会发生。

有两种方法可以解决这个问题:

1)当你的activity的onSaveInstanceState被调用并发布到你正在尝试附加的片段时,会发生这种情况,因为android现在不会保存片段的状态,它会抛出一个exception。 为了克服这一点,如果你不保存你的片段的状态,尝试使用

commitAllowingStateLoss() ,同时提交事务。

2)为了非常安全,在附加片段之前检查您的活动是否处于正确的状态,请在onPause中使用以下代码:

  boolean isInCorrectState; public void onCreate{ super.onCreate(); isInCorrectState = true; } public void onPause() { super.onPause(); if(isFinishing()){ isInCorrectState = false; } } 

现在使用这个标志来检查你的活动是否处于正确的状态,或在附加片段之前..意义附加片段iff isInCorrectState == true

对我来说,原因是别的。

在我的Loader.onLoaderReset()我清除了适配器的数据。 当我离开应用程序时,onDestroy()导致加载程序重置,从而清除了FragmentStatePagerAdapter 。 我认为它导致适配器清除对它的碎片的所有引用,但不知何故, FragmentManager没有注意到并抛出exception。 对我来说似乎不是很合乎逻辑。

请注意,对我来说,它发生了Activity.onDestroy()

希望它可以帮助别人。

ViewPager中的片段是固定的,而不是尝试replace适配器中的片段,尝试给出不同的片段集合并更改notifyDataSet,或者利用FrameLayout在视图分页器选项卡的当前片段上显示另一个片段。

有我的解决scheme工作:

滑动手势与ViewPager一起应用于片段级别,禁用默认滑动