putFragment() - Fragment x当前不在FragmentManager中。

5
上述标题已经被问了很多次,但答案似乎与FragmentStatePagerAdapter密切相关,而这与我的问题无关。我直接使用方法putFragment(Bundle, String, Fragment)Android文档中对putFragment(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 fragment都可以使用getArguments()的结果来找到它们的对应项,即使它们目前不在返回栈的顶部 - 例如,如果它们被透明的更高层次的Fragments部分遮挡。
然而,我收到了异常:
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网站上的文档没有提到片段应处于哪些先决状态,我认为应该这样做)。
值得注意的是commit()中的文本,这就是我认为调用发生得太早的原因——可能的答案是如何附加侦听器以在提交后通知您。我只是认为那不存在...
引用:

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

编辑 通过使用可怕的解决方案确认了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();

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


你将同一个 Bundle 实例传递给了两个不同的 Fragment? - G_V
是的。我已经这样做了一段时间了。据我所知,Bundle没有工作部件,它们只是可序列化的数据集合,只要您的架构知道它可以填充另一个Fragment的值,就没有技术上的障碍。 - Graeme
1个回答

3

我自己从未使用过,但你是否看过FragmentManager.executePendingTransactions()?以下是文档中的说明:

在使用FragmentTransaction.commit()提交FragmentTransaction之后,它将被异步地安排在进程的主线程上执行。如果您想立即执行任何此类挂起操作,可以调用此函数(仅限于主线程)来执行此操作。请注意,所有回调和其他相关行为都将在此调用中完成,因此要小心调用位置。

听起来好像符合您的用例。


1
太棒了 - 正是我所需要的。不知道在查看文档时怎么会错过这个。 - Graeme
2
这种情况发生在最优秀的人身上。 - JstnPwll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接