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

PJL*_*PJL 38 android android-fragments

我有一只猴子撞车了

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)
Run Code Online (Sandbox Code Playgroud)

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

然后,FragmentB只需调用getTargetFragmentonCreate方法并在需要时挂起到目标.

现在,我没有做任何的任何东西onSaveInstanceState在它设置为空,做任何方面与目标片段电话saveFragmentInstanceState,putFragment等电话.问题是我应该用它做些什么吗?

提前致谢,

彼得.

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

**编辑1**已修复支持库的版本8(尚未尝试其他版本).

小智 32

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

1.确保从FragmentA启动FragmentB时使用getChildFragmentManager()NOT getFragmentManager()

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

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

相反,使用getParentFragment().我相信Android中存在某种错误,即使你正确地打电话也是如此

fragmentB.setTargetFragment(fragmentA, 0);

然后显示FragmentB,在配置更改后,从FragmentB调用getTargetFragment()将返回自己而不是FragmentA.


and*_*per 14

这是一个解决方法:

把它放在导致问题的片段中:

@Override
public void onSaveInstanceState(final Bundle outState) {
    setTargetFragment(null, -1);
            ...
Run Code Online (Sandbox Code Playgroud)

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


Kje*_*ide 6

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

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

这导致调用“故障保存状态-目标不在片段管理器中”异常。


h-b*_*omb 5

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

为了防止此异常,在onSaveInstanceState中,我们检查了片段管理器中当前的片段.如果存在任何不一致(即,缺少"目标"片段),我们删除了具有该目标集的片段.在我们的例子中,我们只有三个片段,我们设置目标,所以我们确切地知道要寻找什么.

我不相信有任何其他方法来处理这种情况,但如果有人有任何有用的反馈,我将不胜感激.


Fra*_*ior 5

我只是遇到了这个问题,这就是我想发生的事情以及如何解决它:

例如,当设备旋转时,您的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);
        }


    }
Run Code Online (Sandbox Code Playgroud)

这样,每当将FragmentA附加到上下文时,即:发生设备旋转时,如果直接创建FragmentB(如果是,它将在FragmentManager上),就会重置FragmentB的目标。

希望对您有所帮助。


Gop*_*ala 1

Pre-Honeycomb 和 post-Honeycomb 库之间的 onSaveInstance() 生命周期顺序几乎没有变化。请参阅这篇文章了解更多信息:

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