Chapter 3. Fragment Lifecycle and Specialization

This chapter discusses the relationship of the lifecycle of fragments to that of activities, and demonstrates the appropriate programming actions at the various points in the lifecycle. The special purpose fragment classes ListFragment and DialogFragment are introduced with coverage of their use and how their behavior in the activity lifecycle differs from that of standard fragments.

The following topics are covered in this chapter:

By the end of this chapter, we will be able to coordinate the setup and teardown of fragments within their host activities, and be able to effectively utilize the ListFragment and DialogFragment classes.

One of the challenges of developing Android applications is assuring that our applications effectively handle the lifecycle of the application's activities. During the lifetime of an application, a given activity may be created, destroyed, and recreated many times. A simple action such as a user rotating a device from a portrait to landscape orientation, or vice-versa, normally causes the visible activity to be completely destroyed and recreated using the appropriate resources for the new orientation. Applications that do not cooperate effectively with this natural lifecycle will often crash or behave in some other undesirable manner.

As we know, each fragment instance exists within a single activity; therefore, that fragment must cooperate in some way with the activity lifecycle. In fact, not only do fragments cooperate with the activity lifecycle but also they are intimately connected.

In both the setup and display phase and hide and teardown phase, fragments provide many of the same lifecycle-related callback methods as activities. In addition, fragments provide additional lifecycle-related callback methods that relate to the fragment's relationship to the containing activity.

As our applications become more sophisticated and we work with more specialized implementations of the fragment class, understanding the fragment class' lifecycle and the relationship to the activity lifecycle is essential.

Fragment setup and display is a multiphase process involving the fragment's association with an activity, the fragments' creation, and the standard lifecycle events of moving the activity into the running state (also known as the resumed or active state). Understanding the behavior of the lifecycle events and the associated callback methods is essential for using fragments effectively. Once we have an understanding of the lifecycle events and the callback methods, we'll look at just how the event callback methods are used.

The following diagram shows the sequence of lifecycle-related callback method calls that occur on fragments and activities during setup and display:

Understanding fragment setup and display

As you might expect, in most cases, the first step in the setup and display of a fragment occurs in the activity's onCreate method. In most cases, the activity calls the setContentView method from within the activity's onCreate callback method, which then loads the layout resource and triggers the activity's association with the contained fragments.

Notice what happens next. Before the fragment is ever created, the fragment is attached to the activity. The fragment is first notified of the attachment and receives a reference to the activity through the onAttach callback method. The activity is then notified and receives a reference to the fragment through the onAttachFragment callback method.

Although attaching the fragment to the activity prior to creating the fragment may seem unexpected, doing so is useful. In many cases, the fragment needs access to the activity during the creation process, because the activity often contains information that the fragment will display or that is otherwise important to the fragment creation process.

With the fragment attached to the activity, the fragment then performs general creation work in the onCreate method and then constructs the contained view hierarchy in the onCreateView method.

When an activity contains multiple fragments, Android calls the four methods: Fragment.onAttach, Activity.onAttachFragment, Fragment.onCreate, and Fragment.onCreateView in succession for one fragment before making any calls to these methods for the next fragment. This allows each fragment to complete the process of attachment and creation before the next fragment begins that process.

Once the sequence of calling these four methods completes for all the fragments, the remaining setup and display callback methods are called individually in succession for each fragment.

After the activity completes execution of its onCreate method, Android then calls each fragment's onActivityCreated method. The onActivityCreated method indicates that all views and fragments created by the activity's layout resource are now fully constructed and can be safely accessed.

At this point, the fragment receives the standard lifecycle callbacks on the onStart and onResume methods, just after the activity methods of the same name are each called. Any work performed in the fragment's onStart and onResume methods is very much like the work performed in the corresponding methods within an activity.

For many fragments, the only methods in this part of their lifecycle that are overridden are the onCreate and onCreateView methods, as we saw in the examples in the previous chapters.

Just as fragments behave in a similar way to activities during setup and display, they also behave in a similar way during hide and teardown, as shown in the following diagram:

Understanding fragment hide and teardown

Initially during hide and teardown, fragments behave just as activities. When the user switches to another activity, each fragment's onPause, onSaveInstanceState, and onStop methods are called. For each method, the fragment implementation is called first, followed by the activity implementation.

After the onStop method is called, fragments begin to behave a little differently than activities. Consistent with the separation of fragment creation from fragment view hierarchy creation, fragment view hierarchy destruction is separate from fragment destruction. Following the call to the activity's onStop method, the fragment's onDestroyView method is called indicating that the view hierarchy returned by the fragment's onCreateView method is being destroyed. The fragment's onDestroy method is then called followed by the fragment's onDetach method. At this point, the fragment has no association with an activity and any calls to the getActivity method will return null.

For activities containing multiple fragments, Android calls the sequence of the three methods, onDestroyView, onDestroy, and onDetach, for an individual fragment, before beginning the sequence of calling these three methods for the next fragment. This groups the process of destroying and detaching each fragment similar to the way Android groups the process of attaching and creating each fragment. Once this sequence completes for all fragments, Android then calls the activity's onDestroy method.

For the most part, lifecycle management for a fragment is very much like that of an activity. There is, however, one important exception: the two-phase nature of fragment creation and destruction. Fragments separate the creation and destruction of the fragment from the fragment's contained view hierarchy. This is because fragments have the ability to exist and be associated with an activity in the absence of the fragment's view hierarchy.

There are many scenarios where an activity may contain multiple fragments, but have only a subset of those fragments visible at any point in time. In such a case, the contained fragments can all have their onAttach and onCreate methods called. But the call to each fragment's onCreateView method is delayed until the time comes for the app to make the contents of that fragment visible. Similarly, when the time comes to hide the contents of a fragment, only the fragment's onDestroyView method is called, not the onDestroy and onDetach methods.

This behavior comes into play when fragments are dynamically managed within an activity. This behavior allows the overhead of associating a fragment with an activity and initializing the fragment's state to occur only once while being able to easily change the visibility of the fragment's view hierarchy. This is important when we explicitly manage the visibility of fragments using the FragmentTransaction class, and in certain action bar features that manage fragments. We'll talk about these issues in the next two chapters.