失败保存状态 - 目标不在片段管理器中 (setTargetFragment)



我有一个猴子崩溃,由此

java.lang.IllegalStateException: Failure saving state: FragmentB has target not in fragment manager: FragmentA
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1561)
at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:475)
at com.acme.ParentActivity.onSaveInstanceState(Unknown Source)

基本上,FragmentA 加载 FragmentB,并调用setTargetFragment来设置 FragmentB 的目标片段。

然后,FragmentB 只需在其 onCreate 方法中调用 getTargetFragment,并在需要时挂在目标上。

现在,我在与目标片段的任何onSaveInstanceState调用中都没有做任何事情,将其设置为空,进行任何saveFragmentInstanceStateputFragment等调用。问题是我应该用它做点什么吗?

提前感谢,

彼得。

**

编辑 1 **我正在使用旧版本的支持库,并且感觉这可能会在最新版本中修复,如果是这种情况,将进一步测试并提供进一步的更新。但是,仍然有兴趣知道我是否应该对我当前没有做的目标片段做任何事情。

**

编辑 1 ** 使用支持库版本 8 修复(尚未尝试其他(。

实际上,您应该做两件事来解决此问题:

1. 确保从 FragmentA 启动 FragmentB 时使用 getChildFragmentManager(( 而不是 getFragmentManager((

调用getChildFragmentManager((将返回托管Fragment的FragmentManager

,而getFragmentManager((将返回托管Activity的FragmentManager。 使用 getChildFragmentManager(( 很重要,因为您将一个片段嵌套在另一个片段中,因此父片段应该负责处理嵌套片段的任何事务。 如果你使用 getFragmentManager((,你会遇到你现在遇到的问题。

2. 不要使用 setTargetFragment(( 和 getTargetFragment((,它们在使用 getChildFragmentManager(( 时不起作用

相反,请使用getParentFragment((。 我相信现在Android中存在某种错误,即使您正确调用

fragmentB.setTargetFragment(fragmentA, 0);

然后显示 FragmentB,在

配置更改后,从 FragmentB 调用 getTargetFragment(( 将返回自身而不是 FragmentA。

这是一个解决方法:

将其放在导致问题的片段中:

@Override
public void onSaveInstanceState(final Bundle outState) {
    setTargetFragment(null, -1);
            ...

并记得在需要时将其设置为真正的目标片段。

在显示来自另一个片段的 DialogFrament 并在 DialogFragment 上使用 setTargetFragment 时,我遇到了这个问题。在显示 DialogFragment 时使用 getChildFragmentManager(( 解决了该问题。

  1. 活动 A 添加了片段 A
  2. FragmentA
  3. 使用 ActivityA 的 FragmentManager 添加了 DialogFragmentB。
  4. 称为dialogFragmentB.setTargetFragment(fragmentA(
  5. 删除了片段 A 并添加了片段 A 的新实例
  6. 与 ActivityA 关联的 FragmentManager 仍然包含 DialogFragmentB,该 DialogFragmentB 将 FragmentA 的第一个实例作为目标片段。

这导致调用"失败保存状态 - 目标不在片段管理器中"异常。

我们最近遇到了这个问题。我们实现了扩展 android.support.v4.app 的自定义适配器。FragmentStatePagerAdapter.与 android.support.v4.app。FragmentManager,我们在寻呼机中设置了几个片段,并在寻呼机之外设置了其他几个片段。片段在单个活动中进行管理。在某些情况下,我们将非分页片段的目标(使用 setTargetFragment(设置为可能包含也可能不包含在分页适配器中的片段。因为 FragmentStatePagerAdapter 只维护一定数量的片段,所以设置为目标的片段以及 FragmentStatePagerAdapter 认为不再需要的片段将被销毁......如果具有这些目标的片段仍然存在,则可能处于不一致的状态。这导致每当应用程序失去焦点(当屏幕关闭或应用程序进入后台时(时(即调用 onSaveInstanceState 时(都会引发异常。

为了防止出现这种异常,在 onSaveInstanceState 中,我们检查了片段管理器中当前有哪些片段。如果有任何不一致(即缺少"目标"片段(,我们删除了设置了该目标片段的片段。在我们的例子中,我们只有三个片段来设定目标,所以我们确切地知道要寻找什么。

我不相信有任何其他方法可以处理此案,但如果有人有任何有用的反馈,将不胜感激。

我刚刚遇到了这个问题,这就是我认为正在发生的事情以及我如何解决它:

例如,您的 FragmentA 实例将被销毁,并且正在创建另一个实例,当存在设备轮换时。发生这种情况时,您的 FragmentB 会继续保存对不再存在的 FragmentA 的引用。

在这种情况下,您必须将 FragmentB 的目标重置为新的 FragmentA 实例。

我在 FragmentA 中使用以下代码执行此操作:

@Override
    public void onAttach(Context context) {
        super.onAttach(context);
        FragmentB fragment = (FragmentB) getFragmentManager().findFragmentByTag(FragmentBtag);
        if (fragment != null) {
            fragment.setTargetFragment(this, 0);
        }

    }

这样,每当 FragmentA 附加到上下文时,即:发生设备轮换,如果 FragmentB 是第一手创建的,则 FragmentB 的目标将被重置(如果是这样,它将在 FragmentManager 上(。

我希望它有所帮助。

确保您已将两个片段都添加到后退堆栈中!

在"目标"片段

之上为结果添加新的"调用"片段时,我遇到了这个问题。最初,我遇到了同样的错误,每当我使用它们时,只要我将两个片段添加到后堆栈中,就会停止发生。

该问题发生在屏幕旋转时,因此很容易重现。

在 Pre-HoneyComb 和 Post-Honeycomb 库之间的 onSaveInstance(( 生命周期顺序方面几乎没有变化。有关详细信息,请参阅本文:

http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html

就我而言,问题是关于在错误的片段上调用setTargetFragment

是: FragmentA.setTargetFragment(FragmentB);

应该是: FragmentB.setTargetFragment(FragmentA);

最新更新