Fragments were introduced in Honeycomb (Android 3.0) to help developers deal with the increased screen real estate on tablets, particularly when in landscape orientation. In order to help developers make their phone apps compatible with tablets as well, Google released a compatibility package that allows developers to use the Fragments API as far back as 1.6.
What is a Fragment?
A Fragment is essentially a sub-Activity hosted inside another Activity. By modularizing different components of the UI and displaying them in Fragments, it makes it very easy for developers to re-use these components across various Activities.
The main use case is the design pattern Google suggests when designing an app for both portrait and landscape orientation. Google’s example is a scenario in which an application in landscape mode displays a list of items on the left with a detail view on the right; in portrait mode, only the list or detail view is visible at any given time. In this case, both Fragments (the list and the details) are hosted in the same Activity when in landscape mode and in separate activities when in portrait mode. Clicking on a list item updates the details Fragment when in landscape mode and launches a new Activity in portrait mode. This is easily achievable by creating a separate xml layout in layout-land that includes the second Fragment, and then checking if the second Fragment is null inside the first Activity to determine which action to take next.
Overview of five cool features
Fragments have five particularly neat features that make them very appealing to developers.
1: Fragments can be invisible.
In the documentation, Google mentions that Fragments may be UI-less and claims this might be useful if you wanted to have a hidden worker Fragment. This made me wonder which thread Fragments are run on. I assumed they were run on the UI thread, though my searching didn’t yield much evidence that this was the case. I created an app to test, and my Fragment was running on the main thread both with a UI and without.
I’m sure there is a good use case in mind for the hidden Fragment, but it seems to me that a hidden Fragment would be better-suited to be a “worker” if it was running off the UI thread.
2: Fragments can enforce the hosting Activity to implement specific callback methods, enabling Fragment-to-Activity communication.
By defining an interface inside the Fragment and then checking for the implementation of this interface during the Fragment’s onAttach method, the Fragment can throw an Exception if the implementation is missing. Then, the Fragment is able to communicate with the Activity via these callbacks any time an event or information needs to be propagated up.
3: The hosting Activity can get a reference to any of its Fragments and execute its methods, enabling Activity-to-Fragment communication.
From the hosting Activity, a reference to any embedded Fragment can be obtained by calling:
getFragmentManager().findFragmentById(id);
Passing in the id of the Fragment to locate.
Then, by casting the Fragment as a specific type, any public method inside can be called, thus allowing Activity-to-Fragment communication.
4: Fragments can have their own BackStack that will interact with the Back button.
Much like Activities, Fragments have the ability to keep a BackStack of “states” to create a History for the Fragment to traverse when the Back button is pressed. By calling “addToBackStack” before you commit a change to the FragmentTransaction, the current Fragment state will be saved to the BackStack to be recalled later.
5: Fragments can add items to the Action Bar.
Fragments can even receive the onOptionsItemSelected call when an item is selected, although the hosting Activity will be first to receive this call and can choose to handle the Action Bar press instead.
Conclusion
I think Google did a great job engineering the Fragments API in Honeycomb, and I am very glad it made them backwards compatible all the way to 1.6. It makes the idea of supporting both portrait and landscape modes in my applications a lot more appealing since the components can be re-used, and the idea of combining multiple Fragments in landscape mode is more palatable than re-designing the portrait UI.