Now we come to the most misunderstood of all of the mechanisms implemented by the FragmentManager - the BackStack.
This is a stack of BackStackEntries each of which records a transaction. To add a BackStackEntry to the BackStack all you need to do is use the addToBackStack method, supplying an optional tag if you want to.
The key to understanding the BackStack is know that when the user presses the back key the last transaction added to the stack is undone. The BackStack is like an undo stack for FragmentManager transactions. So if you have a transaction that removes a Fragment and you add this to the BackStack then the back key adds the Fragment.
Notice that for the Fragment to be added back it has to still exist and so any Fragment that is removed by a transaction that is added to the BackStack is not destroyed but put into a stop state ready to be reactivated.
In this sense the BackStack is like an "overflow" for the FragmentManager. This is the reason that the findFragmentByTag method will return a Fragment is it is still added to the FragmentManager or if it is on the BackStack. The Fragment may not be currently added to the FragmentManager but it still exists.
If you remove a Fragment from the FragmentManager and don't add it to the BackStack then the Fragment is destroyed as the system assumes you no longer want it.
Because of this behaviour the BackStack is often used simply to keep a Fragment from being destroyed - this isn't a good use of the BackStack.
The BackStack is provided so that the user can navigate using the back button as if your Fragments were web pages i.e. the user can navigate Fragment changes in the style of a web browser. This is very useful when Fragments are generated and displayed in some arbitrary and user defined order that it makes sense to reverse but this isn't always the case. There are many situations when using the BackStack is a nonsense and hence to use it just to keep a Fragment alive is also nonsense.
In the case of our two Fragment example the user swaps between Fragments 1,2,1,2,1,2 and so on. Putting this on the BackStack would allow the user to go back though the sequence of swaps, 1,2,1,2,1,2 which is fairly pointless.
Don't be fooled into thinking that the BackStack somehow keeps a record of each Fragment's state - it isn't a history in that sense.
For example, if the you did add each Fragment swap in our example to the BackStack, then each press of the back button would reverse the swaps, but the Fragments would display the data they had at the last swap.
To see this in action add:
before the final commit in the onClick event handler.
Now you can swap the Fragments and step back through the swaps. As already mentioned, this isn't of any use in practice. You can also see that this isn't a history by entering some data. If you enter 1 in the first Fragment, then 2 in the second, then 3 in the next appearance of the first fragment and then 4 when you show the second again and press the back button you will see the 3 in the first Fragment but when you press the back button again you will see 4, and then 3 again. The Fragments are swapped by the undoing of the transaction but they aren't restored to their earlier states. There are only two Fragments; these just have their current state.
The BackStack undoes the transaction not any change in state of the Fragments.
Don't use the BackStack unless it makes sense to navigate back through the sequence of Fragment transactions and don't use it just to make a Fragment persist after you have removed it from the FragmentManager.
If you do decide to use the BackStack don't feel the need to push every transaction onto it. It may be that some don't need to be undone, but be careful you don't end up with an illogical undo sequence.
For example if Fragment1 was considered to be a "main" screen and Fragment2 a "secondary" you could arrange the UI so that the Button loaded Fragment2 and the back button to unload it. In this case you would push the transaction that loaded Fragment 2 when the Button was used on the BackStack, so that it could be undone, but not the initial load of Fragment1. The user could then load Fragment2 using the button and undo the load by pressing the back button so returning Fragment1.
As well as the user begin able to pop the BackStack using the back button you can also work with it under program control. This isn't usually necessary but you can determine how many entries are on the BackStack using:
and you can get the item at position p on the stack using:
As the stack is zero-based, the top of the stack, tos, is at
and you can get the entry on the tos using:
You can also pop the BackStack using:
or one of its variants. This has the same effect as the user clicking the back button.
If you find yourself contemplating using such facilities you need to think very hard about your implementation as they are only needed in very few situations and they quickly become very complicated and error-prone.
If you would like an exercise that proves the point, try to write code that swaps the top two items on the BackStack without making the stack bigger. You will think it's easy - but try it and make sure you maintain consistency, i.e. the BackStack has to correspond to the current state of the FragmentManager and the View.
You can use the layout editor to create static arrangements of Fragments to build up a UI displayed on a large single screen.
Use the suffix system to create layouts that apply to different size or orientation of the devices screen.
If you need to arrange for Fragments to share a single container then you need to generate the Fragments dynamically and use the FragmentManager to look after them.
When you add a Fragment you add it to the FragmentManager and optionally display its UI in the specified container.
You can remove the UI from the container without removing the Fragment from the FragmentManager using the detach method and display it in a container using attach.
A general approach to using multiple Fragments in a single Activity is to add the Fragments to the FragmentManager and detach all but one Fragment from each container.
To swap Fragments detach the currently displayed Fragment and attach the Fragment you want to display.
You can animate Fragment changes.
The BackStack is used to provide a web browser like navigation to the Fragments you display. This isn't always appropriate.
The BackStack is a record of transactions and popping it undoes the last stacked transaction.
Any Fragment removed by a transaction is destroyed unless it is pushed on the BackStack when it is preserved in a stopped state.
Do not use the BackStack simply to preserve the state of a Fragment - its purpose is navigation.
Next we need to look at one of the almost unavoidable uses of Fragments - the Dialog Fragment. This is usually regarded as a difficult topic but now you know about Fragments it should seem very easy.
Meanwhile if you have any questions on what we've covered so far please let me know using the comments.
You can download the code for the programs from the CodeBin (note you have to register first).