28

在 onResume() 的某些情况下,我在使用 FragmentStatePagerAdapter 的活动中得到了这个。使用设备的后退按钮时。不总是。不可重现。

我正在使用支持包 v4,最新版本 (8)。

已经用谷歌搜索,没有成功找到有用的答案。

查看源代码,它被扔在这里: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);
}

但是为什么fragment < 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;
}
4

7 回答 7

15

如果您的 ViewPager 布局在片段内(不是活动):

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

于 2014-02-03T18:20:27.793 回答
10

我在这里遇到了同样的错误,但出于另一个原因。

就我而言,我在 FragmentStatePagerAdapter 中覆盖了 getItemPosition。我的想法是返回位置,如果项目存在,或者 POSITION_NONE,如果它不再存在。

好吧,我的问题是,当我的收藏为空时,我返回了 POSITION_NONE。这打破了一切。

我的解决方法是在我有一个空集合时返回 POSITION_UNCHANGED。

希望它可以帮助别人。

于 2013-12-22T21:04:00.807 回答
8

理解这个错误的两个关键点是:

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

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

private static final int NUM_ITEMS = 2;

ViewPager mPager = /** instantiate viewpager **/;
mPager.setOffscreenPageLimit(NUM_ITEMS-1);

你可以在这里读到它:

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

于 2012-07-02T15:24:40.800 回答
5

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

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

于 2012-07-02T15:30:06.730 回答
4

此异常意味着您正在尝试将片段附加到不再是正确状态以附加片段的活动。这意味着,每当我们尝试附加片段(尤其是通过异步调用)时,很有可能有人按下了后退按钮,并且在附加片段时活动正在合并中被破坏。这并不总是可重现的,因为它只是一个竞争条件,并且可能并不总是发生..

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

1)当您调用活动的 onSaveInstanceState 并将其发布到您尝试附加片段时,就会发生这种情况,因为 android 现在无法保存片段的状态,它将引发异常。为了克服这个问题,如果您没有保存片段的状态,请尝试使用

commitAllowingStateLoss(),同时提交事务。

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

    boolean isInCorrectState;

    public void onCreate{
    super.onCreate();
    isInCorrectState = true;
    }

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

现在使用此标志在附加片段之前检查您的活动是否处于正确状态。. 意味着附加片段 iff isInCorrectState == true

于 2013-11-02T20:59:17.830 回答
2

对我来说,原因是别的。

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

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

希望它可以帮助某人。

于 2013-06-24T16:48:28.027 回答
0

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

有我的解决方案有效:

在 Fragment 级别与 ViewPager 一起应用的滑动手势,默认滑动禁用

于 2013-11-20T12:42:04.497 回答