问题
I'm using the Android Compatibility library to implement fragments and have extended the layout sample so that a fragment contains a button which fires off another fragment.
In the selection pane on the left I have 5 selectable items - A B C D E
.
Each loads up a fragment (via FragmentTransaction:replace
) in the details pane - a b c d e
Now I've extended fragment e
to contain a button which loads up another fragment e1
also in the details pane. I've done this on fragment e
's onClick method as follows:
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(R.id.details_frag, newFrag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
If I make the following selections:
E - e - e1 - D - E
Then fragment e
is in the details pane. This is fine and what I want. However, if I hit the back
button at this point it does nothing. I have to click it twice because e1
is still on the stack. Furthermore after clicking around I got a null pointer exception in onCreateView:
To 'solve' this problem I added the following whenever A B C D E
is selected:
FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
fm.popBackStack();
}
Just wondering whether this is the correct solution or whether I should be doing something different?
回答1:
Well there are a few ways to go about this depending on the intended behavior, but this link should give you all the best solutions and not surprisingly is from Dianne Hackborn
http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42
Essentially you have the following options
- Use a name for your initial back stack state and use
FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)
. - Use
FragmentManager.getBackStackEntryCount()
/getBackStackEntryAt().getId()
to retrieve the ID of the first entry on the back stack, andFragmentManager.popBackStack(int id, FragmentManager.POP_BACK_STACK_INCLUSIVE)
. FragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
is supposed to pop the entire back stack... I think the documentation for that is just wrong. (Actually I guess it just doesn't cover the case where you pass inPOP_BACK_STACK_INCLUSIVE
),
回答2:
The other clean solution if you don't want to pop all stack entries...
getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().beginTransaction().replace(R.id.home_activity_container, fragmentInstance).addToBackStack(null).commit();
This will clean the stack first and then load a new fragment, so at any given point you'll have only single fragment in stack
回答3:
Thanks to Joachim answer, I use the code to clear all back stack entry finally.
// In your FragmentActivity use getSupprotFragmentManager() to get the FragmentManager.
// Clear all back stack.
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
for (int i = 0; i < backStackCount; i++) {
// Get the back stack fragment id.
int backStackId = getSupportFragmentManager().getBackStackEntryAt(i).getId();
getSupportFragmentManager().popBackStack(backStackId,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
} /* end of for */
回答4:
I have researched a lot for cleaning Backstack, and finally see Transaction BackStack and its management. Here is the solution that worked best for me.
// CLEAR BACK STACK.
private void clearBackStack() {
final FragmentManager fragmentManager = getSupportFragmentManager();
while (fragmentManager.getBackStackEntryCount() != 0) {
fragmentManager.popBackStackImmediate();
}
}
The above method loops over all the transactions in the backstack and removes them immediately one at a time.
Note: above code sometime not work and i face ANR because of this code,so please do not try this.
Update below method remove all fregment of that "name" from backstack.
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE);
- name If non-null, this is the name of a previous back state to look for; if found, all states up to that state will be popped. The
- POP_BACK_STACK_INCLUSIVE flag can be used to control whether the named state itself is popped. If null, only the top state is popped.
回答5:
I'm using a similar code as those that use the while loop but I call the entry count in every loop... so I suppose it's somewhat slower
FragmentManager manager = getFragmentManager();
while (manager.getBackStackEntryCount() > 0){
manager.popBackStackImmediate();
}
回答6:
As written in How to pop fragment off backstack and by @LarsH here, we can pop several fragments from top down to specifical tag (together with the tagged fragment) using this method:
fragmentManager?.popBackStack ("frag", FragmentManager.POP_BACK_STACK_INCLUSIVE);
Substitute "frag" with your fragment's tag. Remember that first we should add the fragment to backstack with:
fragmentTransaction.addToBackStack("frag")
If we add fragments with addToBackStack(null)
, we won't pop fragments that way.
回答7:
// pop back stack all the way
final FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
int entryCount = fm.getBackStackEntryCount();
while (entryCount-- > 0) {
fm.popBackStack();
}
来源:https://stackoverflow.com/questions/5802141/is-this-the-right-way-to-clean-up-fragment-back-stack-when-leaving-a-deeply-nest