【问题标题】:FragmentStatePagerAdapter IllegalStateException: <MyFragment> is not currently in the FragmentManagerFragmentStatePagerAdapter IllegalStateException: <MyFragment> 当前不在 FragmentManager 中
【发布时间】:2012-07-03 00:41:44
【问题描述】:

在 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的索引

实例化片段的代码:

@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;
}

【问题讨论】:

标签: android fragment


【解决方案1】:

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

mViewPager.setAdapter(new MyFragmentStatePagerAdapter(getChildFragmentManager()));

【讨论】:

  • 谢谢你。这个“getChildFragmentManager()”工作正常!
  • 对我没用。我有一个嵌套的 viewpager,我在父片段中使用 getChildFragmentManager() 方法。使用该方法引发异常。
  • 你也拯救了我的一天!!!当离开具有 viewpager 的片段,然后返回它时,viewpager 的内容是空的。我尝试了许多低效的方法,例如以编程方式来回移动页面以刷新视图,但是在我使用 getChildFragmentManager() 的那一刻,内容又恢复了活力!感激不尽
【解决方案2】:

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

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

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

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

希望对其他人有所帮助。

【讨论】:

  • 谢谢,我实际上遇到了完全相同的情况,并且已修复它,顺便说一句,您有动态数量的片段还是恒定的?
  • 嗨@242Eld。这是一个动态数量的片段。这取决于来自 WS 的数据。
【解决方案3】:

理解这个 bug 的两个关键点是:

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

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

private static final int NUM_ITEMS = 2;

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

你可以在这里阅读:

ViewPager Fragments getting destroyed over time?

【讨论】:

  • 我不明白抛出异常的逻辑,因为 ViewPager 没有保留片段的状态......如果片段被销毁,为什么 ViewPager 不只是重新创建它?无论如何,每次我加载活动时,我都会设置一个实例化片段的新适配器,我不明白为什么它仍然试图访问其他片段............
  • 所有这些片段的东西真的很可怕,我已经有 4 个不同的例外,所有这些都与尝试访问不再存在的东西有关“片段不再存在”,“没有为片段找到 id 0xcf 的视图” ,“片段不再在片段管理器中”(忘记了第四个)。堆栈跟踪甚至没有显示我的任何代码行,也没有关于此的常用指南或示例,只有一些非常简单的教程,它们总是有效的。但是,一旦它变得更复杂一点......繁荣。
  • 嗯...是的,我记得我也被 ViewPager 片段的生命周期/管理弄糊涂了。开发者网站上的文档记录不是很好,而且源代码相当密集-_-
  • 但是在研究了源码之后有意义吗?对我来说,设计/API 似乎有问题......但如果你说这只是缺乏文档,我会花时间......有一天......研究源代码。
  • 我不是 100% 确定研究源代码会有所帮助...我从来没有觉得我已经实现了 100% 的工作解决方案,只是在等待我的应用程序随机中断我,因为修复我感到不可靠......但也许我确实正确地实施了它,谁知道呢。我所知道的是,文档对ViewPager 如何管理其容器片段并不是很清楚,所以也许研究文档可以让您更深入地了解这一点......
【解决方案4】:

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

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

【讨论】:

  • 说实话,我不记得了。如果异常很少发生,try catch 会有所帮助。也许该问题已在更新版本的支持包中得到修复(例如,它们现在允许嵌套片段,这会在旧版本中导致异常)。
  • 我真的很喜欢这个答案!非常感谢。
【解决方案5】:

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

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

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

【讨论】:

    【解决方案6】:

    对我来说,原因是别的。

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

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

    希望对某人有所帮助。

    【讨论】:

    • 我很好奇,你是怎么解决的?我遇到同样的事情。当我删除代码以清除在 onLoaderReset 期间调用的适配器时,我不再收到错误消息。只是担心泄漏..
    • 我不会担心泄漏。就个人而言,我大部分时间都留空onLoaderReset()。请参阅此答案,它提供了更多详细信息:stackoverflow.com/a/16337401/1118475
    【解决方案7】:

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

    我的解决方案有效:

    Swipe Gesture applied at Fragment level along with ViewPager with it's default swipe disabled

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-01
      • 2013-07-12
      • 1970-01-01
      • 1970-01-01
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多