putFragment() - Fragment x is not currently in the FragmentManager

2.3k views Asked by At

The above title has been asked a lot, but answers seem closely tied to FragmentStatePagerAdapter which has nothing to do with my problem. I'm using the method putFragment(Bundle, String, Fragment) directly.

The Android Documentation for putFragment(Bundle, String, Fragment) says:

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.

However the following code throws an exception:

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);

The reason I'm using the above is so that both ContentFragment and ActionBar fragment can use the result of getArguments() to find their opposite number, even if they aren't currently in the top of the backstack - such as if they are partially occluded by transparent Fragments higher in the stack.

However, I get the exception:

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

Can I conclude from this that commit() simply puts the transaction on a stack to be done on the UI thread and the putFragment() calls are happening before that transaction is being carried out? Or am I misunderstanding something? (The documentation on the Android site doesn't say anything about prerequisite states for the Fragments to be in which I assume it should).

It's worth noting the text in commit() which is why I assume the call is happening too early - A possible answer being how to attach a listener to a transaction to notify you when it has been commit()ed. I just don't think that exists...

Schedules a commit of this transaction. The commit does not happen immediately; it will be scheduled as work on the main thread to be done the next time that thread is ready.

EDIT

Confirmed that commit() is the problem by using a terrible solution:

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();

Real solutions still very much appreciated.

1

There are 1 answers

2
JstnPwll On BEST ANSWER

I've never used it myself, but have you looked at FragmentManager.executePendingTransactions()? Here's what the documentation says:

After a FragmentTransaction is committed with FragmentTransaction.commit(), it is scheduled to be executed asynchronously on the process's main thread. If you want to immediately executing any such pending operations, you can call this function (only from the main thread) to do so. Note that all callbacks and other related behavior will be done from within this call, so be careful about where this is called from.

It sounds like it matches your use case.