【问题标题】:putFragment() - Fragment x is not currently in the FragmentManagerputFragment() - Fragment x 当前不在 FragmentManager 中
【发布时间】:2014-11-20 14:04:14
【问题描述】:

上面的标题被问了很多,但答案似乎与FragmentStatePagerAdapter 密切相关,这与我的问题无关。我直接用putFragment(Bundle, String, Fragment)这个方法。

Android DocumentationputFragment(Bundle, String, Fragment) 表示:

Put a reference to a fragment in a Bundle. This Bundle can be persisted as saved state, and when later restoring getFragment(Bundle, String) will return the current instance of the same fragment.

Parameters
* bundle        The bundle in which to put the fragment reference.
* key           The name of the entry in the bundle.
* fragment  The Fragment whose reference is to be stored.

但是下面的代码会抛出异常:

Bundle bundle = new Bundle();
CustomFragment actionBarFragment = getActionBarFragment();
CustomFragment contentFragment   = getContentFragment();
actionBarFragment.setArguments(bundle);
contentFragment.setArguments(bundle);

FragmentTransaction mTransaction = getSupportFragmentManager().beginTransaction();
mTransaction.add(R.id.actionBarPane, actionBarFragment);
mTransaction.add(R.id.contentPane,   contentFragment);
mTransaction.commit();

getSupportFragmentManager().putFragment(bundle, "ContentFragment", contentFragment);
getSupportFragmentManager().putFragment(bundle, "ActionBar", actionBarFragment);

我使用上面的原因是 ContentFragment 和 ActionBar 片段都可以使用getArguments() 的结果来找到它们相反的数字,即使它们当前不在后台堆栈的顶部 - 例如如果它们被堆栈中较高的透明片段部分遮挡。

但是,我得到了例外:

11-20 13:44:17.842: E/Default Exception Handler(12466): Caused by: java.lang.IllegalStateException: Fragment CustomFragment{4219bdb8 id=0x7f06002e com.test.CustomFragment1} is not currently in the FragmentManager

我是否可以由此得出结论,commit() 只是将事务放在堆栈上以在 UI 线程上完成,并且在执行该事务之前发生 putFragment() 调用?还是我误解了什么? (Android 网站上的文档没有说明我认为应该处于的 Fragments 的先决条件)。

值得注意的是commit() 中的文本,这就是为什么我认为呼叫发生得太早的原因 - 一个可能的答案是如何将侦听器附加到事务以在事务被 commit()ed 时通知您。我只是不认为存在......

安排此事务的提交。提交不会立即发生;它将被安排在主线程上的工作,以便在该线程下一次准备好时完成。

编辑

通过使用糟糕的解决方案确认commit() 是问题所在:

mTransaction.commit();
new Thread() {
    public void run() {
        while(!contentFragment.isAdded()) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {}
        }
        getSupportFragmentManager().putFragment(bundle, "ContentFragment", contentFragment);
        getSupportFragmentManager().putFragment(bundle, "ActionBar", actionBarFragment);
    };
}.start();

仍然非常感谢真正的解决方案。

【问题讨论】:

  • 您将同一个包实例传递给两个单独的片段?
  • 是的。这样做有一段时间了。据我了解,Bundles 没有工作部分,它们只是一个可序列化的数据集合,只要您的架构知道它可以填充另一个 Fragment 的值,就没有技术理由不这样做。

标签: android android-fragments fragment-backstack


【解决方案1】:

我自己从来没有用过,但是你看过FragmentManager.executePendingTransactions()吗?文档是这样说的:

在 FragmentTransaction 提交后 FragmentTransaction.commit(),预定执行 在进程的主线程上异步。如果你想 立即执行任何此类挂起的操作,您可以调用它 函数(仅来自主线程)这样做。请注意,所有回调 和其他相关行为将在此调用中完成,所以 注意从哪里调用它。

听起来它符合您的用例。

【讨论】:

  • 太棒了——正是我所需要的。不知道我在查看文档时是怎么错过的。
  • :) 这发生在我们最好的人身上。
猜你喜欢
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-06
相关资源
最近更新 更多