Android Adventures - Managing Fragments |
Written by Mike James | ||||||
Thursday, 22 May 2014 | ||||||
Page 5 of 5
The BackStackNow 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. Summary
ConclusionNext 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).
Android Adventures - Mastering Fragments & DialogsContentsThis book is currently being revised. Chapter 5 and later refer to an earlier version of Android Studio - revisit for updates.
If you are interested in creating custom template also see: Custom Projects In Android Studio To be informed about new articles on I Programmer, install the I Programmer Toolbar, subscribe to the RSS feed, follow us on, Twitter,Facebook, Google+ or Linkedin, or sign up for our weekly newsletter.
Comments
or email your comment to: comments@i-programmer.info |
||||||
Last Updated ( Saturday, 25 July 2015 ) |