From 1064dd9117cb8151d301e251d6fa7cc38661817c Mon Sep 17 00:00:00 2001 From: Scott Main Date: Mon, 17 Jan 2011 16:06:12 -0800 Subject: docs: move the fragments dev guide into fundamentals topic Change-Id: If6a9751e78db23e76256e179db99aa0e29126f85 --- docs/html/guide/topics/fundamentals/fragments.jd | 815 +++++++++++++++++++++++ 1 file changed, 815 insertions(+) create mode 100644 docs/html/guide/topics/fundamentals/fragments.jd (limited to 'docs/html/guide/topics/fundamentals/fragments.jd') diff --git a/docs/html/guide/topics/fundamentals/fragments.jd b/docs/html/guide/topics/fundamentals/fragments.jd new file mode 100644 index 0000000..045a1e8 --- /dev/null +++ b/docs/html/guide/topics/fundamentals/fragments.jd @@ -0,0 +1,815 @@ +page.title=Fragments +@jd:body + +
+
+ +

Quickview

+
    +
  • Fragments decompose application functionality and UI into reusable modules
  • +
  • Add multiple fragments to a screen to avoid switching activities
  • +
  • Fragments have their own lifecycle, state, and back stack
  • +
  • Fragments require API Level HONEYCOMB or greater
  • +
+ +

In this document

+
    +
  1. Design Philosophy
  2. +
  3. Creating a Fragment +
      +
    1. Adding a user interface
    2. +
    3. Adding a fragment to an activity
    4. +
    +
  4. +
  5. Managing Fragments
  6. +
  7. Performing Fragment Transactions
  8. +
  9. Communicating with the Activity +
      +
    1. Creating event callbacks to the activity
    2. +
    3. Adding items to the Action Bar
    4. +
    +
  10. +
  11. Handling the Fragment Lifecycle +
      +
    1. Coordinating with the activity lifecycle
    2. +
    +
  12. +
  13. Example
  14. +
+ +

Key classes

+
    +
  1. {@link android.app.Fragment}
  2. +
  3. {@link android.app.FragmentManager}
  4. +
  5. {@link android.app.FragmentTransaction}
  6. +
+ +

Related samples

+
    +
  1. ApiDemos
  2. +
+
+
+ +

A {@link android.app.Fragment} represents a behavior or a portion of user interface in an +{@link android.app.Activity}. You can combine multiple fragments in a single activity to build a +multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a +modular section of an activity, which has its own lifecycle, receives its own input events, and +which you can add or remove while the activity is running.

+ +

A fragment must always be embedded in an activity and the fragment's lifecycle is directly +affected by the activity's lifecycle. For example, when the activity is paused, so are all +fragments in it, and when the activity is destroyed, so are all fragments. However, while an +activity is running (it is in the resumed lifecycle state), you can +manipulate each fragment independently, such as add or remove them. When you perform such a +fragment transaction, you can it to a back stack managed by the +activity—each back stack entry in the activity is a record of the fragment transaction that +occurred. The back stack allows the user to reverse a fragment transaction (navigate backwards), +by pressing the BACK key.

+ +

When you add a fragment as a part of your activity layout, it lives in a {@link +android.view.ViewGroup} inside the activity's view hierarchy and defines its own layout of views. +You can insert a fragment into your activity layout by declaring the fragment in the activity's +layout file, as a {@code <fragment>} element, or from your application code by adding it to an +existing {@link android.view.ViewGroup}. However, a fragment is not required to be a part of the +activity layout; you may also use a fragment as an invisible worker for the activity.

+ +

This document describes how to build your application to use fragments, including +how fragments can maintain their state when added to the activity's back stack, share +events with the activity and other fragments in the activity, contribute to the activity's action +bar, and more.

+ + +

Design Philosophy

+ +

Android introduced fragments in Android 3.0 (API Level "Honeycomb"), primarily to support more +dynamic and flexible UI designs on large screens, such as tablets. Because a +tablet's screen is much larger than that of a mobile phone, there's more room to combine and +interchange UI components. Fragments allow such designs without the need for you to manage complex +changes to the view hierarchy. By dividing the layout of an activity into fragments, you become able +to modify the activity's appearance at runtime and preserve those changes in a back stack +that's managed by the activity.

+ +

For example, a news application can use one fragment to show a list of articles on the +left and another fragment to display an article on the right—both fragments appear in one +activity, side by side, and each fragment has its own set of lifecycle callback methods and handle +their own user input events. Thus, instead of using one activity to select an article and another +activity to read the article, the user can select an article and read it all within the same +activity, as illustrated in figure 1.

+ + +

Figure 1. An example of how two UI modules that are +typically separated into two activities can be combined into one activity, using fragments.

+ + +

A fragment should be a modular and reusable component in your application. That is, because the +fragment defines its own layout and its own behavior using its own lifecycle callbacks, you +can include one fragment in multiple activities. This is especially important because it allows you +to adapt your user experience to different screen sizes. For instance, you might include multiple +fragments in an activity only when the screen size is sufficiently large, and, when it is not, +launch separate activities that use different fragments.

+ +

For example—to continue with the news application example—the application can embed +two +fragments in Activity A, when running on an extra large screen (a tablet, for example). +However, on a normal-sized screen (a phone, for example), +there's not be enough room for both fragments, so Activity A includes only the fragment for +the list of articles, and when the user selects an article, it starts Activity B, which +includes the fragment to read the article. Thus, the application supports both design patterns +suggested in figure 1.

+ + + +

Creating a Fragment

+ +
+ +

Figure 2. The lifecycle of a fragment (while its +activity is running).

+
+ +

To create a fragment, you must create a subclass of {@link android.app.Fragment} (or an existing +subclass of it). The {@link android.app.Fragment} class has code that looks a lot like +an {@link android.app.Activity}. It contains callback methods similar to an activity, such +as {@link android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()}, +{@link android.app.Fragment#onPause onPause()}, and {@link android.app.Fragment#onStop onStop()}. In +fact, if you're converting an existing Android application to use fragments, you might simply move +code from your activity's callback methods into the respective callback methods of your +fragment.

+ +

Usually, you should implement at least the following lifecycle methods:

+ +
+
{@link android.app.Fragment#onCreate onCreate()}
+
The system calls this when creating the fragment. Within your implementation, you should +initialize essential components of the fragment that you want to retain when the fragment is +paused or stopped, then resumed.
+
{@link android.app.Fragment#onCreateView onCreateView()}
+
The system calls this when it's time for the fragment to draw its user interface for the +first time. To draw a UI for your fragment, you must return a {@link android.view.View} from this +method that is the root of your fragment's layout. You can return null if the fragment does not +provide a UI.
+
{@link android.app.Activity#onPause onPause()}
+
The system calls this method as the first indication that the user is leaving the +fragment (though it does not always mean the fragment is being destroyed). This is usually where you +should commit any changes that should be persisted beyond the current user session (because +the user might not come back).
+
+ +

Most applications should implement at least these three methods for every fragment, but there are +several other callback methods you should also use to handle various stages of the +fragment lifecycle. All the lifecycle callback methods are discussed more later, in the section +about Handling the Fragment Lifecycle.

+ + +

There are also a few subclasses that you might want to extend, instead of the base {@link +android.app.Fragment} class:

+ +
+
{@link android.app.DialogFragment}
+
Displays a floating dialog. Using this class to create a dialog is a good alternative to using +the dialog helper methods in the {@link android.app.Activity} class, because you can +incorporate a fragment dialog into the back stack of fragments managed by the activity, +allowing the user to return to a dismissed fragment.
+ +
{@link android.app.ListFragment}
+
Displays a list of items that are managed by an adapter (such as a {@link +android.widget.SimpleCursorAdapter}), similar to {@link android.app.ListActivity}. It provides +several methods for managing a list view, such as the {@link +android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} callback to +handle click events.
+ +
{@link android.preference.PreferenceFragment}
+
Displays a hierarchy of {@link android.preference.Preference} objects as a list, similar to +{@link android.preference.PreferenceActivity}. This is useful when creating a "settings" +activity for your application.
+
+ + +

Adding a user interface

+ +

A fragment is usually used as part of an activity's user interface and contributes its own +layout to the activity.

+ +

To provide a layout for a fragment, you must implement the {@link +android.app.Fragment#onCreateView onCreateView()} callback method, which the Android system calls +when it's time for the fragment to draw its layout. Your implementation of this method must return a +{@link android.view.View} that is the root of your fragment's layout.

+ +

Note: If your fragment is a subclass of {@link +android.app.ListFragment}, the default implementation returns a {@link android.widget.ListView} from +{@link android.app.Fragment#onCreateView onCreateView()}, so you don't need to implement it.

+ +

To return a layout from {@link +android.app.Fragment#onCreateView onCreateView()}, you can inflate it from a layout resource defined in XML. To +help you do so, {@link android.app.Fragment#onCreateView onCreateView()} provides a +{@link android.view.LayoutInflater} object.

+ +

For example, here's a subclass of {@link android.app.Fragment} that loads a layout from the +{@code example_fragment.xml} file:

+ +
+public static class ExampleFragment extends Fragment {
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        // Inflate the layout for this fragment
+        return inflater.inflate(R.layout.example_fragment, container, false);
+    }
+}
+
+ + + +

The {@code container} parameter passed to {@link android.app.Fragment#onCreateView +onCreateView()} is the parent {@link android.view.ViewGroup} (from the activity's layout) in which +your fragment layout +will be inserted. The {@code savedInstanceState} parameter is a {@link android.os.Bundle} that +provides data about the previous instance of the fragment, if the fragment is being resumed +(restoring state is discussed more in the section about Handling the +Fragment Lifecycle).

+ +

The {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} method takes +three arguments:

+ + +

Now you've seen how to create a fragment that provides a layout. Next, you need to add +the fragment to your activity.

+ + + +

Adding a fragment to an activity

+ +

Usually, a fragment contributes a portion of UI to the host activity, which is embedded as a part +of the activity's overall view hierarchy. There are two ways you can add a fragment to the activity +layout:

+ + + + +

Adding a fragment without a UI

+ +

The examples above show how to add a fragment to your activity in order to provide a UI. However, +you can also use a fragment to provide a background behavior for the activity without presenting +additional UI.

+ +

To add a fragment without a UI, add the fragment from the activity using {@link +android.app.FragmentTransaction#add(Fragment,String)} (supplying a unique string "tag" for the +fragment, rather than a view ID). This adds the fragment, but, because it's not associated with a +view in the activity layout, it does not receive a call to {@link +android.app.Fragment#onCreateView onCreateView()}. So you don't need to implement that method.

+ +

Supplying a string tag for the fragment isn't strictly for non-UI fragments—you can also +supply string tags to fragments that do have a UI—but if the fragment does not have a +UI, then the string tag is the only way to identify it. If you want to get the fragment from the +activity later, you need to use {@link android.app.FragmentManager#findFragmentByTag +findFragmentByTag()}.

+ +

For an example activity that uses a fragment as a background worker, without a UI, see the {@code +FragmentRetainInstance.java} sample.

+ + + +

Managing Fragments

+ +

To manage the fragments in your activity, you need to use {@link android.app.FragmentManager}. To +get it, call {@link android.app.Activity#getFragmentManager()} from your activity.

+ +

Some things that you can do with {@link android.app.FragmentManager} include:

+ + + +

For more information about these methods and others, refer to the {@link +android.app.FragmentManager} class documentation.

+ +

As demonstrated in the previous section, you can also use {@link android.app.FragmentManager} +to open a {@link android.app.FragmentTransaction}, which allows you to perform transactions, such as +add and remove fragments.

+ + +

Performing Fragment Transactions

+ +

A great feature about using fragments in your activity is the ability to add, remove, replace, +and perform other actions with them, in response to user interaction. Each set of changes that you +commit to the activity is called a transaction and you can perform one using APIs in {@link +android.app.FragmentTransaction}. You can also save each transaction to a back stack managed by the +activity, allowing the user to navigate backward through the fragment changes (similar to navigating +backward through activities).

+ +

You can acquire an instance of {@link android.app.FragmentTransaction} from the {@link +android.app.FragmentManager} like this:

+ +
+FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()};
+FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#openTransaction()};
+
+ +

Each transaction is a set of changes that you want to perform at the same time. You can set +up all the changes you want to perform for a given transaction using methods such as {@link +android.app.FragmentTransaction#add add()}, {@link android.app.FragmentTransaction#remove remove()}, +and {@link android.app.FragmentTransaction#replace replace()}. Then, to apply the transaction +to the activity, you must call {@link android.app.FragmentTransaction#commit()}.

+ + +

Before you call {@link +android.app.FragmentTransaction#commit()}, however, you might want to call {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, in order to add the transaction +to a back stack of fragment transactions. This back stack is managed by the activity and allows +the user to return to the previous fragment state, by pressing the BACK key.

+ +

For example, here's how you can replace one fragment with another, and preserve the previous +state in the back stack:

+ +
+// Create new fragment and transaction
+Fragment newFragment = new ExampleFragment();
+FragmentTransaction transaction = getFragmentManager().openTransaction();
+
+// Replace whatever is in the fragment_container view with this fragment,
+// and add the transaction to the back stack
+transaction.replace(R.id.fragment_container, newFragment);
+transaction.addToBackStack(null);
+
+// Commit the transaction
+transaction.commit();
+
+ +

In this example, {@code newFragment} replaces whatever fragment (if any) is currently in the +layout container identified by the {@code R.id.fragment_container} ID. By calling {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, the replace transaction is +saved to the back stack so the user can reverse the transaction and bring back the +previous fragment by pressing the BACK key.

+ +

If you add multiple changes to the transaction (such as another {@link +android.app.FragmentTransaction#add add()} or {@link android.app.FragmentTransaction#remove +remove()}) and call {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, then all changes applied +before you call {@link android.app.FragmentTransaction#commit commit()} are added to the +back stack as a single transaction and the BACK key will reverse them all together.

+ +

The order in which you add changes to a {@link android.app.FragmentTransaction} doesn't matter, +except:

+ + +

If you do not call {@link android.app.FragmentTransaction#addToBackStack(String) +addToBackStack()} when you perform a transaction that removes a fragment, then that fragment is +destroyed when the transaction is committed and the user cannot navigate back to it. Whereas, if you +do call {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} when +removing a fragment, then the fragment is stopped and will be resumed if the user navigates +back.

+ +

Tip: For each fragment transaction, you can apply a transition +animation, by calling {@link android.app.FragmentTransaction#setTransition setTransition()} before +you commit.

+ +

Calling {@link android.app.FragmentTransaction#commit()} does not perform the transaction +immediately. Rather, it schedules it to run on the activity's UI thread (the "main" thread) as soon +as the thread is able to do so. If necessary, however, you may call {@link +android.app.FragmentManager#executePendingTransactions()} from your UI thread to immediately execute +transactions submitted by {@link android.app.FragmentTransaction#commit()}. Doing so is +usually not necessary unless the transaction is a dependency for jobs in other threads.

+ +

Caution: You can commit a transaction using {@link +android.app.FragmentTransaction#commit commit()} only prior to the activity saving its +state (when the user leaves the activity). If you attempt to commit after that point, an +exception will be thrown. This is because the state after the commit can be lost if the activity +needs to be restored. For situations in which its okay that you lose the commit, use {@link +android.app.FragmentTransaction#commitAllowingStateLoss()}.

+ + + + +

Communicating with the Activity

+ +

Although a {@link android.app.Fragment} is implemented as an object that's independent from an +{@link android.app.Activity} and can be used inside multiple activities, a given instance of +a fragment is directly tied to the activity that contains it.

+ +

Specifically, the fragment can access the {@link android.app.Activity} instance with {@link +android.app.Fragment#getActivity()} and easily perform tasks such as find a view in the +activity layout:

+ +
+View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list);
+
+ +

Likewise, your activity can call methods in the fragment by acquiring a reference to the +{@link android.app.Fragment} from {@link android.app.FragmentManager}, using {@link +android.app.FragmentManager#findFragmentById findFragmentById()} or {@link +android.app.FragmentManager#findFragmentByTag findFragmentByTag()}. For example:

+ +
+ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
+
+ + +

Creating event callbacks to the activity

+ +

In some cases, you might need a fragment to share events with the activity. A good way to do that +is to define a callback interface inside the fragment and require that the host activity implement +it. When the activity receives a callback through the interface, it can share the information with +other fragments in the layout as necessary.

+ +

For example, if a news application has two fragments in an activity—one to show a list of +articles (fragment A) and another to display an article (fragment B)—then fragment A must tell +the activity when a list item is selected so that it can tell fragment B to display the article. In +this case, the {@code OnArticleSelectedListener} interface is declared inside fragment A:

+ +
+public static class FragmentA extends ListFragment {
+    ...
+    // Container Activity must implement this interface
+    public interface OnArticleSelectedListener {
+        public void onArticleSelected(Uri articleUri);
+    }
+    ...
+}
+
+ +

Then the activity that hosts the fragment implements the {@code OnArticleSelectedListener} +interface and +overrides {@code onArticleSelected()} to notify fragment B of the event from fragment A. To ensure +that the host activity implements this interface, fragment A's {@link +android.app.Fragment#onAttach onAttach()} callback method (which the system calls when adding +the fragment to the activity) instantiates an instance of {@code OnArticleSelectedListener} by +casting the {@link android.app.Activity} that is passed into {@link android.app.Fragment#onAttach +onAttach()}:

+ +
+public static class FragmentA extends ListFragment {
+    OnArticleSelectedListener mListener;
+    ...
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        try {
+            mListener = (OnArticleSelectedListener) activity;
+        } catch (ClassCastException e) {
+            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
+        }
+    }
+    ...
+}
+
+ +

If the activity has not implemented the interface, then the fragment throws a +{@link java.lang.ClassCastException}. +On success, the {@code mListener} member holds a reference to activity's implementation of +{@code OnArticleSelectedListener}, so that fragment A can share events with the activity by calling +methods defined by the {@code OnArticleSelectedListener} interface. For example, if fragment A is an +extension of {@link android.app.ListFragment}, each time +the user clicks a list item, the system calls {@link android.app.ListFragment#onListItemClick +onListItemClick()} in the fragment, which then calls {@code onArticleSelected()} to share +the event with the activity:

+ +
+public static class FragmentA extends ListFragment {
+    OnArticleSelectedListener mListener;
+    ...
+    @Override
+    public void onListItemClick(ListView l, View v, int position, long id) {
+        // Append the clicked item's row ID with the content provider Uri
+        Uri noteUri = ContentUris.{@link android.content.ContentUris#withAppendedId withAppendedId}(ArticleColumns.CONTENT_URI, id);
+        // Send the event and Uri to the host activity
+        mListener.onArticleSelected(noteUri);
+    }
+    ...
+}
+
+ +

The {@code id} parameter passed to {@link +android.app.ListFragment#onListItemClick onListItemClick()} is the row ID of the clicked item, +which the activity (or other fragment) uses to fetch the article from the application's {@link +android.content.ContentProvider}.

+ +

More information about +using a content provider is available in the Content Providers document.

+ + + +

Adding items to the Action Bar

+ +

Your fragments can contribute menu items to the activity's Options Menu (and, consequently, the Action Bar) by implementing +{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. In order +for this method to receive calls, however, you must call {@link +android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} during {@link +android.app.Fragment#onCreate(Bundle) onCreate()}, to indicate that the fragment +would like to add items to the Options Menu (otherwise, the fragment will not receive a call to +{@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()}).

+ +

Any items that you then add to the Options Menu from the fragment are appended to the existing +menu items. The fragment also receives callbacks to {@link +android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} when a menu item +is selected.

+ +

You can also register a view in your fragment layout to provide a context menu by calling {@link +android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}. When the user opens +the context menu, the fragment receives a call to {@link +android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo) +onCreateContextMenu()}. When the user selects an item, the fragment receives a call to {@link +android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}.

+ +

Note: Although your fragment receives an on-item-selected callback +for each menu item it adds, the activity is first to receive the respective callback when the user +selects a menu item. If the activity's implementation of the on-item-selected callback does not +handle the selected item, then the event is passed to the fragment's callback. This is true for +the Options Menu and context menus.

+ +

For more information about menus, see Creating +Menus and Using the Action Bar.

+ + + + +

Handling the Fragment Lifecycle

+ +
+ +

Figure 3. The activity lifecycle's affect on the fragment +lifecycle.

+
+ +

Managing the lifecycle of a fragment is a lot like managing the lifecycle of an activity. Like +an activity, a fragment can exist in three states:

+ +
+
Resumed
+
The fragment is visible in the running activity.
+ +
Paused
+
Another activity is in the foreground and has focus, but the activity in which this +fragment lives is still visible (the foreground activity is partially transparent or doesn't +cover the entire screen).
+ +
Stopped
+
The fragment is not visible. Either the host activity has been stopped or the +fragment has been removed from the activity but added to the back stack. A stopped fragment is +still alive (all state and member information is retained by the system). However, it is no longer +visible to the user and will be killed if the activity is killed.
+
+ +

Also like an activity, you can retain the state of a fragment using a {@link +android.os.Bundle}, in case the activity's process is killed and you need to restore the +fragment state when the activity is recreated. You can save the state during the fragment's {@link +android.app.Fragment#onSaveInstanceState onSaveInstanceState()} callback and restore it during +either {@link android.app.Fragment#onCreate onCreate()}, {@link +android.app.Fragment#onCreateView onCreateView()}, or {@link +android.app.Fragment#onActivityCreated onActivityCreated()}. For more information about saving +state, see the Activities +document.

+ +

The most significant difference in lifecycle between an activity and a fragment is how one is +stored in its respective back stack. An activity is placed into a back stack of activities +that's managed by the system when it's stopped, by default (so that the user can navigate back +to it with the BACK key, as discussed in Tasks and Back Stack). +However, a fragment is placed into a back stack managed by the host activity only when you +explicitly request that the instance be saved by calling {@link +android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} during a transaction that +removes the fragment.

+ +

Otherwise, managing the fragment lifecycle is very similar to managing the activity +lifecycle. So, the same practices for managing the activity +lifecycle also apply to fragments. What you also need to understand, though, is how the life +of the activity affects the life of the fragment.

+ + +

Coordinating with the activity lifecycle

+ +

The lifecycle of the activity in which the fragment lives directly affects the lifecycle of the +fragment, such that each lifecycle callback for the activity results in a similar callback for each +fragment. For example, when the activity receives {@link android.app.Activity#onPause}, each +fragment in the activity receives {@link android.app.Fragment#onPause}.

+ +

Fragments have a few extra lifecycle callbacks, however, that handle unique interaction with the +activity in order to perform actions such as build and destroy the fragment's UI. These additional +callback methods are:

+ +
+
{@link android.app.Fragment#onAttach onAttach()}
+
Called when the fragment has been associated with the activity (the {@link +android.app.Activity} is passed in here).
+
{@link android.app.Fragment#onCreateView onCreateView()}
+
Called to create the view hierarchy associated with the fragment.
+
{@link android.app.Fragment#onActivityCreated onActivityCreated()}
+
Called when the activity's {@link android.app.Activity#onCreate +onCreate()} method has returned.
+
{@link android.app.Fragment#onDestroyView onDestroyView()}
+
Called when the view hierarchy associated with the fragment is being removed.
+
{@link android.app.Fragment#onDetach onDetach()}
+
Called when the fragment is being disassociated from the activity.
+
+ +

The flow of a fragment's lifecycle, as it is affected by its host activity, is illustrated +by figure 3. In this figure, you can see how each successive state of the activity determines which +callback methods a fragment may receive. For example, when the activity has received its {@link +android.app.Activity#onCreate onCreate()} callback, a fragment in the activity receives no more than +the {@link android.app.Fragment#onActivityCreated onActivityCreated()} callback.

+ +

Once the activity reaches the resumed state, you can freely add and remove fragments to the +activity. Thus, only while the activity is in the resumed state can the lifecycle of a fragment +change independently.

+ +

However, when the activity leaves the resumed state, the fragment again is pushed through its +lifecycle by the activity.

+ + + + +

Example

+ +

To bring everything discussed in this document together, here's an example of an activity +using two fragments to create a two-pane layout. The activity below includes one fragment to +show a list of Shakespeare play titles and another to show a summary of the play when selected +from the list. It also demonstrates how to provide different configurations of the fragments, +based on the screen configuration.

+ +

Note: The complete source code for this activity is available in +{@code +FragmentLayout.java}.

+ +

The main activity applies a layout in the usual way, during {@link +android.app.Activity#onCreate onCreate()}:

+ +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java main} + +

The layout applied is {@code fragment_layout.xml}:

+ +{@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout} + +

Using this layout, the system instantiates the {@code TitlesFragment} (which lists the play +titles) as soon as the activity loads the layout, while the {@link android.widget.FrameLayout} +(where the fragment for showing the play summary will go) consumes space on the right side of the +screen, but remains empty at first. As you'll see below, it's not until the user selects an item +from the list that a fragment is placed into the {@link android.widget.FrameLayout}.

+ +

However, not all screen configurations are wide enough to show both the list of +plays and the summary, side by side. So, the layout above is used only for the landscape +screen configuration, by saving it at {@code res/layout-land/fragment_layout.xml}.

+ +

Thus, when the screen is in portrait orientation, the system applies the following layout, which +is saved at {@code res/layout/fragment_layout.xml}:

+ +{@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout} + +

This layout includes only {@code TitlesFragment}. This means that, when the device is in +portrait orientation, only the list of play titles is visible. So, when the user clicks a list +item in this configuration, the application will start a new activity to show the summary, +instead of loading a second fragment.

+ +

Next, you can see how this is accomplished in the fragment classes. First is {@code +TitlesFragment}, which shows the list of Shakespeare play titles. This fragment extends {@link +android.app.ListFragment} and relies on it to handle most of the list view work.

+ +

As you inspect this code, notice that there are two possible behaviors when the user clicks a +list item: depending on which of the two layouts is active, it can either create and display a new +fragment to show the details in the same activity (adding the fragment to the {@link +android.widget.FrameLayout}), or start a new activity (where the fragment can be shown).

+ +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java titles} + +

The second fragment, {@code DetailsFragment} shows the play summary for the item selected from +the list from {@code TitlesFragment}:

+ +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details} + +

Recall from the {@code TitlesFragment} class, that, if the user clicks a list item and the +current layout does not include the {@code R.id.details} view (which is where the +{@code DetailsFragment} belongs), then the application starts the {@code DetailsActivity} +activity to display the content of the item.

+ +

Here is the {@code DetailsActivity}, which simply embeds the {@code DetailsFragment} to display +the selected play summary when the screen is in portrait orientation:

+ +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java +details_activity} + +

Notice that this activity finishes itself if the configuration is landscape, so that the main +activity can take over and display the {@code DetailsFragment} alongside the {@code TitlesFragment}. +This can happen if the user begins the {@code DetailsActivity} while in portrait orientation, but +then rotates to landscape (which restarts the current activity).

+ + +

For more samples using fragments (and complete source files for this example), +see the sample code available in +ApiDemos (available for download from the Samples SDK component).

+ + -- cgit v1.1