4

Is there any way, how to clear backStack of support FragmentManager without calling onCreateView() in stored fragments?

I understand fragment lyfe cycle and calling onDestroyView() and onCreateView() when it is popped. http://developer.android.com/guide/components/fragments.html#Creating

Also I know how to pop all fragments from backstack with

mFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);

or

for(int i = 0; i < mFragmentManager.getBackStackEntryCount(); ++i) {            
     mFragmentManager.popBackStack();
}

but both ways are calling onCreateView() and other lyfe cycle methods until to onDestroyView() and onDestroy().

But is there any way, how to clear this backstack with calling only from onDestroyView() and not from onCreateView() (inside of fragments)?

Or is there any way how to do replace transaction with clearing previous fragments?

For example, I want clear backstact before I do transaction:

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentManager.beginTransaction().replace(R.id.content, fragment).commit();
Kikju
  • 787
  • 1
  • 6
  • 17
  • Is your goal to avoid recreation of fragment views as they are popped out of the stack because you know that when the popping is complete, the final fragment state will be "destroyed"? – Bob Snyder Jul 11 '15 at 21:07
  • yes, this is exacly what I want – Kikju Jul 12 '15 at 06:37
  • By any chance, were you able to solve this? I'm having the same problem right now when doing Single activity architecture. – Edwin Martinez Jan 27 '20 at 07:19
  • @EdwinMartinez not really. What I did (I'm not proud of it), ugly workaround by "cleaningBackstack" property in the activity. So code in activity looks like this: ``` cleaningBackstack = true; fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); fragmentManager.executePendingTransactions(); cleaningBackstack = false; ``` and in the onViewCreated in fragments: ``` if (a.isCleaningBackstack()) return; ``` – Kikju Jan 28 '20 at 08:16

1 Answers1

0

I haven't found a simple solution to this issue. I'm almost certain there is no feature of FragmentManager or Fragment that allows you to control which lifecycle method are called when a fragment is popped from the stack. I'll outline two possible approaches. Each has some undesirable aspects.

The first approach assumes the fragments you are popping out of the backstack are children of an activity. If they are children of a fragment, the method still applies, just a different type of parent object.

Add a boolean member mClearingBackStack to the activity (or parent fragment) with a getter method. Set the boolean only when you are starting a complete clear of the backstack. In the fragment lifecycle methods where you want to disable processing, get the flag and modify the processing accordingly. For onCreateView() through onDestroyView(), the fragment will be attached and the host activity available with getActivity(). Cast it to whatever your activity class is to use the flag's getter method.

Because popBackStack() is asynchronous, clearing the flag must be done only after the stack unwinding completes. I haven't tried it, but I think posting a Runnable after calling popBackStack() to clear the flag should work. Because the Runnable needs to go at the end of the queue, View.post() must be used instead of Activity.runOnUiThread(). An alternative is to call executePendingTransactions() to wait for the stack unwinding to complete.

The second approach is cleaner, if your design can accommodate it. Create a place-holder fragment that is a child of your activity and parent to all your other fragments. For all the fragment transactions you have now, use the new fragment's FragmentManager, obtained using getChildFragmentManager(). When you want to clear all those transactions, instead of popping the child fragment manager's stack, remove or replace the parent fragment in the activity's fragment manager. When the parent fragment is removed, all of its children are destroyed and go through the teardown steps, onDestroyView(), onDestroy(), etc. but not all the steps that would occur if its backstack were unwound. This approach is much simpler and more maintainable than the first, but requires you to rework your fragment hierarchy. An additional problem with this approach is that you must add some code to handle the Back action with a fragment hierarchy. The problem and various solutions are described here.

Community
  • 1
  • 1
Bob Snyder
  • 37,759
  • 6
  • 111
  • 158