Fragment.java revision b1ad5977bc8178b6d350ebe9099daded4c1ef603
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
19import android.content.ComponentCallbacks;
20import android.content.Context;
21import android.content.Intent;
22import android.content.res.Configuration;
23import android.os.Bundle;
24import android.os.Parcel;
25import android.os.Parcelable;
26import android.util.AttributeSet;
27import android.util.SparseArray;
28import android.view.ContextMenu;
29import android.view.LayoutInflater;
30import android.view.Menu;
31import android.view.MenuInflater;
32import android.view.MenuItem;
33import android.view.View;
34import android.view.ViewGroup;
35import android.view.ContextMenu.ContextMenuInfo;
36import android.view.View.OnCreateContextMenuListener;
37import android.view.animation.Animation;
38import android.widget.AdapterView;
39
40import java.lang.reflect.InvocationTargetException;
41import java.util.HashMap;
42
43final class FragmentState implements Parcelable {
44    static final String VIEW_STATE_TAG = "android:view_state";
45
46    final String mClassName;
47    final int mIndex;
48    final boolean mFromLayout;
49    final int mFragmentId;
50    final int mContainerId;
51    final String mTag;
52    final boolean mRetainInstance;
53
54    Bundle mSavedFragmentState;
55
56    Fragment mInstance;
57
58    public FragmentState(Fragment frag) {
59        mClassName = frag.getClass().getName();
60        mIndex = frag.mIndex;
61        mFromLayout = frag.mFromLayout;
62        mFragmentId = frag.mFragmentId;
63        mContainerId = frag.mContainerId;
64        mTag = frag.mTag;
65        mRetainInstance = frag.mRetainInstance;
66    }
67
68    public FragmentState(Parcel in) {
69        mClassName = in.readString();
70        mIndex = in.readInt();
71        mFromLayout = in.readInt() != 0;
72        mFragmentId = in.readInt();
73        mContainerId = in.readInt();
74        mTag = in.readString();
75        mRetainInstance = in.readInt() != 0;
76        mSavedFragmentState = in.readBundle();
77    }
78
79    public Fragment instantiate(Activity activity) {
80        if (mInstance != null) {
81            return mInstance;
82        }
83
84        try {
85            mInstance = Fragment.instantiate(activity, mClassName);
86        } catch (Exception e) {
87            throw new RuntimeException("Unable to restore fragment " + mClassName, e);
88        }
89
90        if (mSavedFragmentState != null) {
91            mSavedFragmentState.setClassLoader(activity.getClassLoader());
92            mInstance.mSavedFragmentState = mSavedFragmentState;
93            mInstance.mSavedViewState
94                    = mSavedFragmentState.getSparseParcelableArray(VIEW_STATE_TAG);
95        }
96        mInstance.setIndex(mIndex);
97        mInstance.mFromLayout = mFromLayout;
98        mInstance.mFragmentId = mFragmentId;
99        mInstance.mContainerId = mContainerId;
100        mInstance.mTag = mTag;
101        mInstance.mRetainInstance = mRetainInstance;
102
103        return mInstance;
104    }
105
106    public int describeContents() {
107        return 0;
108    }
109
110    public void writeToParcel(Parcel dest, int flags) {
111        dest.writeString(mClassName);
112        dest.writeInt(mIndex);
113        dest.writeInt(mFromLayout ? 1 : 0);
114        dest.writeInt(mFragmentId);
115        dest.writeInt(mContainerId);
116        dest.writeString(mTag);
117        dest.writeInt(mRetainInstance ? 1 : 0);
118        dest.writeBundle(mSavedFragmentState);
119    }
120
121    public static final Parcelable.Creator<FragmentState> CREATOR
122            = new Parcelable.Creator<FragmentState>() {
123        public FragmentState createFromParcel(Parcel in) {
124            return new FragmentState(in);
125        }
126
127        public FragmentState[] newArray(int size) {
128            return new FragmentState[size];
129        }
130    };
131}
132
133/**
134 * A Fragment is a piece of an application's user interface or behavior
135 * that can be placed in an {@link Activity}.
136 */
137public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener {
138    private static final HashMap<String, Class<?>> sClassMap =
139            new HashMap<String, Class<?>>();
140
141    static final int INITIALIZING = 0;     // Not yet created.
142    static final int CREATED = 1;          // Created.
143    static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
144    static final int STARTED = 3;          // Created and started, not resumed.
145    static final int RESUMED = 4;          // Created started and resumed.
146
147    int mState = INITIALIZING;
148
149    // When instantiated from saved state, this is the saved state.
150    Bundle mSavedFragmentState;
151    SparseArray<Parcelable> mSavedViewState;
152
153    // Index into active fragment array.
154    int mIndex = -1;
155
156    // Internal unique name for this fragment;
157    String mWho;
158
159    // True if the fragment is in the list of added fragments.
160    boolean mAdded;
161
162    // True if the fragment is in the resumed state.
163    boolean mResumed;
164
165    // Set to true if this fragment was instantiated from a layout file.
166    boolean mFromLayout;
167
168    // Number of active back stack entries this fragment is in.
169    int mBackStackNesting;
170
171    // Set as soon as a fragment is added to a transaction (or removed),
172    // to be able to do validation.
173    Activity mImmediateActivity;
174
175    // Activity this fragment is attached to.
176    Activity mActivity;
177
178    // The optional identifier for this fragment -- either the container ID if it
179    // was dynamically added to the view hierarchy, or the ID supplied in
180    // layout.
181    int mFragmentId;
182
183    // When a fragment is being dynamically added to the view hierarchy, this
184    // is the identifier of the parent container it is being added to.
185    int mContainerId;
186
187    // The optional named tag for this fragment -- usually used to find
188    // fragments that are not part of the layout.
189    String mTag;
190
191    // Set to true when the app has requested that this fragment be hidden
192    // from the user.
193    boolean mHidden;
194
195    // If set this fragment would like its instance retained across
196    // configuration changes.
197    boolean mRetainInstance;
198
199    // If set this fragment is being retained across the current config change.
200    boolean mRetaining;
201
202    // If set this fragment has menu items to contribute.
203    boolean mHasMenu;
204
205    // Used to verify that subclasses call through to super class.
206    boolean mCalled;
207
208    // If app has requested a specific animation, this is the one to use.
209    int mNextAnim;
210
211    // The parent container of the fragment after dynamically added to UI.
212    ViewGroup mContainer;
213
214    // The View generated for this fragment.
215    View mView;
216
217    LoaderManagerImpl mLoaderManager;
218    boolean mStarted;
219
220    /**
221     * Default constructor.  <strong>Every</string> fragment must have an
222     * empty constructor, so it can be instantiated when restoring its
223     * activity's state.  It is strongly recommended that subclasses do not
224     * have other constructors with parameters, since these constructors
225     * will not be called when the fragment is re-instantiated; instead,
226     * retrieve such parameters from the activity in {@link #onAttach(Activity)}.
227     */
228    public Fragment() {
229    }
230
231    /**
232     * Create a new instance of a Fragment with the given class name.  This is
233     * the same as calling its empty constructor.
234     *
235     * @param context The calling context being used to instantiate the fragment.
236     * This is currently just used to get its ClassLoader.
237     * @param fname The class name of the fragment to instantiate.
238     * @return Returns a new fragment instance.
239     * @throws NoSuchMethodException The fragment does not have an empty constructor.
240     * @throws ClassNotFoundException The fragment class does not exist.
241     * @throws IllegalArgumentException Bad arguments supplied to fragment class
242     * constructor (should not happen).
243     * @throws InstantiationException Caller does not have permission to instantiate
244     * the fragment (for example its constructor is not public).
245     * @throws IllegalAccessException Caller does not have permission to access
246     * the given fragment class.
247     * @throws InvocationTargetException Failure running the fragment's constructor.
248     */
249    public static Fragment instantiate(Context context, String fname)
250            throws NoSuchMethodException, ClassNotFoundException,
251            IllegalArgumentException, InstantiationException,
252            IllegalAccessException, InvocationTargetException {
253        Class<?> clazz = sClassMap.get(fname);
254
255        if (clazz == null) {
256            // Class not found in the cache, see if it's real, and try to add it
257            clazz = context.getClassLoader().loadClass(fname);
258            sClassMap.put(fname, clazz);
259        }
260        return (Fragment)clazz.newInstance();
261    }
262
263    void restoreViewState() {
264        if (mSavedViewState != null) {
265            mView.restoreHierarchyState(mSavedViewState);
266            mSavedViewState = null;
267        }
268    }
269
270    void setIndex(int index) {
271        mIndex = index;
272        mWho = "android:fragment:" + mIndex;
273   }
274
275    void clearIndex() {
276        mIndex = -1;
277        mWho = null;
278    }
279
280    /**
281     * Subclasses can not override equals().
282     */
283    @Override final public boolean equals(Object o) {
284        return super.equals(o);
285    }
286
287    /**
288     * Subclasses can not override hashCode().
289     */
290    @Override final public int hashCode() {
291        return super.hashCode();
292    }
293
294    @Override
295    public String toString() {
296        StringBuilder sb = new StringBuilder(128);
297        sb.append("Fragment{");
298        sb.append(Integer.toHexString(System.identityHashCode(this)));
299        if (mIndex >= 0) {
300            sb.append(" #");
301            sb.append(mIndex);
302        }
303        if (mFragmentId != 0) {
304            sb.append(" id=0x");
305            sb.append(Integer.toHexString(mFragmentId));
306        }
307        if (mTag != null) {
308            sb.append(" ");
309            sb.append(mTag);
310        }
311        sb.append('}');
312        return sb.toString();
313    }
314
315    /**
316     * Return the identifier this fragment is known by.  This is either
317     * the android:id value supplied in a layout or the container view ID
318     * supplied when adding the fragment.
319     */
320    final public int getId() {
321        return mFragmentId;
322    }
323
324    /**
325     * Get the tag name of the fragment, if specified.
326     */
327    final public String getTag() {
328        return mTag;
329    }
330
331    /**
332     * Return the Activity this fragment is currently associated with.
333     */
334    final public Activity getActivity() {
335        return mActivity;
336    }
337
338    /**
339     * Return true if the fragment is currently added to its activity.
340     */
341    final public boolean isAdded() {
342        return mActivity != null && mActivity.mFragments.mAdded.contains(this);
343    }
344
345    /**
346     * Return true if the fragment is in the resumed state.  This is true
347     * for the duration of {@link #onResume()} and {@link #onPause()} as well.
348     */
349    final public boolean isResumed() {
350        return mResumed;
351    }
352
353    /**
354     * Return true if the fragment is currently visible to the user.  This means
355     * it: (1) has been added, (2) has its view attached to the window, and
356     * (3) is not hidden.
357     */
358    final public boolean isVisible() {
359        return isAdded() && !isHidden() && mView != null
360                && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE;
361    }
362
363    /**
364     * Return true if the fragment has been hidden.  By default fragments
365     * are shown.  You can find out about changes to this state with
366     * {@link #onHiddenChanged}.  Note that the hidden state is orthogonal
367     * to other states -- that is, to be visible to the user, a fragment
368     * must be both started and not hidden.
369     */
370    final public boolean isHidden() {
371        return mHidden;
372    }
373
374    /**
375     * Called when the hidden state (as returned by {@link #isHidden()} of
376     * the fragment has changed.  Fragments start out not hidden; this will
377     * be called whenever the fragment changes state from that.
378     * @param hidden True if the fragment is now hidden, false if it is not
379     * visible.
380     */
381    public void onHiddenChanged(boolean hidden) {
382    }
383
384    /**
385     * Control whether a fragment instance is retained across Activity
386     * re-creation (such as from a configuration change).  This can only
387     * be used with fragments not in the back stack.  If set, the fragment
388     * lifecycle will be slightly different when an activity is recreated:
389     * <ul>
390     * <li> {@link #onDestroy()} will not be called (but {@link #onDetach()} still
391     * will be, because the fragment is being detached from its current activity).
392     * <li> {@link #onCreate(Bundle)} will not be called since the fragment
393     * is not being re-created.
394     * <li> {@link #onAttach(Activity)} and {@link #onActivityCreated(Bundle)} <b>will</b>
395     * still be called.
396     * </ul>
397     */
398    public void setRetainInstance(boolean retain) {
399        mRetainInstance = retain;
400    }
401
402    final public boolean getRetainInstance() {
403        return mRetainInstance;
404    }
405
406    /**
407     * Report that this fragment would like to participate in populating
408     * the options menu by receiving a call to {@link #onCreateOptionsMenu}
409     * and related methods.
410     *
411     * @param hasMenu If true, the fragment has menu items to contribute.
412     */
413    public void setHasOptionsMenu(boolean hasMenu) {
414        if (mHasMenu != hasMenu) {
415            mHasMenu = hasMenu;
416            if (isAdded() && !isHidden()) {
417                mActivity.invalidateOptionsMenu();
418            }
419        }
420    }
421
422    /**
423     * Return the LoaderManager for this fragment, creating it if needed.
424     */
425    public LoaderManager getLoaderManager() {
426        if (mLoaderManager != null) {
427            return mLoaderManager;
428        }
429        mLoaderManager = mActivity.getLoaderManager(mIndex, mStarted);
430        return mLoaderManager;
431    }
432
433    /**
434     * Call {@link Activity#startActivity(Intent)} on the fragment's
435     * containing Activity.
436     */
437    public void startActivity(Intent intent) {
438        mActivity.startActivityFromFragment(this, intent, -1);
439    }
440
441    /**
442     * Call {@link Activity#startActivityForResult(Intent, int)} on the fragment's
443     * containing Activity.
444     */
445    public void startActivityForResult(Intent intent, int requestCode) {
446        mActivity.startActivityFromFragment(this, intent, requestCode);
447    }
448
449    /**
450     * Receive the result from a previous call to
451     * {@link #startActivityForResult(Intent, int)}.  This follows the
452     * related Activity API as described there in
453     * {@link Activity#onActivityResult(int, int, Intent)}.
454     *
455     * @param requestCode The integer request code originally supplied to
456     *                    startActivityForResult(), allowing you to identify who this
457     *                    result came from.
458     * @param resultCode The integer result code returned by the child activity
459     *                   through its setResult().
460     * @param data An Intent, which can return result data to the caller
461     *               (various data can be attached to Intent "extras").
462     */
463    public void onActivityResult(int requestCode, int resultCode, Intent data) {
464    }
465
466    /**
467     * Called when a fragment is being created as part of a view layout
468     * inflation, typically from setting the content view of an activity.  This
469     * will be called both the first time the fragment is created, as well
470     * later when it is being re-created from its saved state (which is also
471     * given here).
472     *
473     * XXX This is kind-of yucky...  maybe we could just supply the
474     * AttributeSet to onCreate()?
475     *
476     * @param activity The Activity that is inflating the fragment.
477     * @param attrs The attributes at the tag where the fragment is
478     * being created.
479     * @param savedInstanceState If the fragment is being re-created from
480     * a previous saved state, this is the state.
481     */
482    public void onInflate(Activity activity, AttributeSet attrs,
483            Bundle savedInstanceState) {
484        mCalled = true;
485    }
486
487    /**
488     * Called when a fragment is first attached to its activity.
489     * {@link #onCreate(Bundle)} will be called after this.
490     */
491    public void onAttach(Activity activity) {
492        mCalled = true;
493    }
494
495    public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
496        return null;
497    }
498
499    /**
500     * Called to do initial creation of a fragment.  This is called after
501     * {@link #onAttach(Activity)} and before
502     * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
503     *
504     * <p>Note that this can be called while the fragment's activity is
505     * still in the process of being created.  As such, you can not rely
506     * on things like the activity's content view hierarchy being initialized
507     * at this point.  If you want to do work once the activity itself is
508     * created, see {@link #onActivityCreated(Bundle)}.
509     *
510     * @param savedInstanceState If the fragment is being re-created from
511     * a previous saved state, this is the state.
512     */
513    public void onCreate(Bundle savedInstanceState) {
514        mCalled = true;
515    }
516
517    /**
518     * Called to have the fragment instantiate its user interface view.
519     * This is optional, and non-graphical fragments can return null (which
520     * is the default implementation).  This will be called between
521     * {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}.
522     *
523     * <p>If you return a View from here, you will later be called in
524     * {@link #onDestroyView} when the view is being released.
525     *
526     * @param inflater The LayoutInflater object that can be used to inflate
527     * any views in the fragment,
528     * @param container If non-null, this is the parent view that the fragment's
529     * UI should be attached to.  The fragment should not add the view itself,
530     * but this can be used to generate the LayoutParams of the view.
531     * @param savedInstanceState If non-null, this fragment is being re-constructed
532     * from a previous saved state as given here.
533     *
534     * @return Return the View for the fragment's UI, or null.
535     */
536    public View onCreateView(LayoutInflater inflater, ViewGroup container,
537            Bundle savedInstanceState) {
538        return null;
539    }
540
541    public View getView() {
542        return mView;
543    }
544
545    /**
546     * Called when the fragment's activity has been created and this
547     * fragment's view hierarchy instantiated.  It can be used to do final
548     * initialization once these pieces are in place, such as retrieving
549     * views or restoring state.  It is also useful for fragments that use
550     * {@link #setRetainInstance(boolean)} to retain their instance,
551     * as this callback tells the fragment when it is fully associated with
552     * the new activity instance.  This is called after {@link #onCreateView}
553     * and before {@link #onStart()}.
554     *
555     * @param savedInstanceState If the fragment is being re-created from
556     * a previous saved state, this is the state.
557     */
558    public void onActivityCreated(Bundle savedInstanceState) {
559        mCalled = true;
560    }
561
562    /**
563     * Called when the Fragment is visible to the user.  This is generally
564     * tied to {@link Activity#onStart() Activity.onStart} of the containing
565     * Activity's lifecycle.
566     */
567    public void onStart() {
568        mCalled = true;
569        mStarted = true;
570        if (mLoaderManager != null) {
571            mLoaderManager.doStart();
572        }
573    }
574
575    /**
576     * Called when the fragment is visible to the user and actively running.
577     * This is generally
578     * tied to {@link Activity#onResume() Activity.onResume} of the containing
579     * Activity's lifecycle.
580     */
581    public void onResume() {
582        mCalled = true;
583    }
584
585    public void onSaveInstanceState(Bundle outState) {
586    }
587
588    public void onConfigurationChanged(Configuration newConfig) {
589        mCalled = true;
590    }
591
592    /**
593     * Called when the Fragment is no longer resumed.  This is generally
594     * tied to {@link Activity#onPause() Activity.onPause} of the containing
595     * Activity's lifecycle.
596     */
597    public void onPause() {
598        mCalled = true;
599    }
600
601    /**
602     * Called when the Fragment is no longer started.  This is generally
603     * tied to {@link Activity#onStop() Activity.onStop} of the containing
604     * Activity's lifecycle.
605     */
606    public void onStop() {
607        mCalled = true;
608    }
609
610    public void onLowMemory() {
611        mCalled = true;
612    }
613
614    /**
615     * Called when the view previously created by {@link #onCreateView} has
616     * been detached from the fragment.  The next time the fragment needs
617     * to be displayed, a new view will be created.  This is called
618     * after {@link #onStop()} and before {@link #onDestroy()}; it is only
619     * called if {@link #onCreateView} returns a non-null View.
620     */
621    public void onDestroyView() {
622        mCalled = true;
623    }
624
625    /**
626     * Called when the fragment is no longer in use.  This is called
627     * after {@link #onStop()} and before {@link #onDetach()}.
628     */
629    public void onDestroy() {
630        mCalled = true;
631        if (mLoaderManager != null) {
632            mLoaderManager.doDestroy();
633        }
634    }
635
636    /**
637     * Called when the fragment is no longer attached to its activity.  This
638     * is called after {@link #onDestroy()}.
639     */
640    public void onDetach() {
641        mCalled = true;
642    }
643
644    /**
645     * Initialize the contents of the Activity's standard options menu.  You
646     * should place your menu items in to <var>menu</var>.  For this method
647     * to be called, you must have first called {@link #setHasOptionsMenu}.  See
648     * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu}
649     * for more information.
650     *
651     * @param menu The options menu in which you place your items.
652     *
653     * @see #setHasOptionsMenu
654     * @see #onPrepareOptionsMenu
655     * @see #onOptionsItemSelected
656     */
657    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
658    }
659
660    /**
661     * Prepare the Screen's standard options menu to be displayed.  This is
662     * called right before the menu is shown, every time it is shown.  You can
663     * use this method to efficiently enable/disable items or otherwise
664     * dynamically modify the contents.  See
665     * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu}
666     * for more information.
667     *
668     * @param menu The options menu as last shown or first initialized by
669     *             onCreateOptionsMenu().
670     *
671     * @see #setHasOptionsMenu
672     * @see #onCreateOptionsMenu
673     */
674    public void onPrepareOptionsMenu(Menu menu) {
675    }
676
677    /**
678     * This hook is called whenever an item in your options menu is selected.
679     * The default implementation simply returns false to have the normal
680     * processing happen (calling the item's Runnable or sending a message to
681     * its Handler as appropriate).  You can use this method for any items
682     * for which you would like to do processing without those other
683     * facilities.
684     *
685     * <p>Derived classes should call through to the base class for it to
686     * perform the default menu handling.
687     *
688     * @param item The menu item that was selected.
689     *
690     * @return boolean Return false to allow normal menu processing to
691     *         proceed, true to consume it here.
692     *
693     * @see #onCreateOptionsMenu
694     */
695    public boolean onOptionsItemSelected(MenuItem item) {
696        return false;
697    }
698
699    /**
700     * This hook is called whenever the options menu is being closed (either by the user canceling
701     * the menu with the back/menu button, or when an item is selected).
702     *
703     * @param menu The options menu as last shown or first initialized by
704     *             onCreateOptionsMenu().
705     */
706    public void onOptionsMenuClosed(Menu menu) {
707    }
708
709    /**
710     * Called when a context menu for the {@code view} is about to be shown.
711     * Unlike {@link #onCreateOptionsMenu}, this will be called every
712     * time the context menu is about to be shown and should be populated for
713     * the view (or item inside the view for {@link AdapterView} subclasses,
714     * this can be found in the {@code menuInfo})).
715     * <p>
716     * Use {@link #onContextItemSelected(android.view.MenuItem)} to know when an
717     * item has been selected.
718     * <p>
719     * The default implementation calls up to
720     * {@link Activity#onCreateContextMenu Activity.onCreateContextMenu}, though
721     * you can not call this implementation if you don't want that behavior.
722     * <p>
723     * It is not safe to hold onto the context menu after this method returns.
724     * {@inheritDoc}
725     */
726    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
727        getActivity().onCreateContextMenu(menu, v, menuInfo);
728    }
729
730    /**
731     * Registers a context menu to be shown for the given view (multiple views
732     * can show the context menu). This method will set the
733     * {@link OnCreateContextMenuListener} on the view to this fragment, so
734     * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be
735     * called when it is time to show the context menu.
736     *
737     * @see #unregisterForContextMenu(View)
738     * @param view The view that should show a context menu.
739     */
740    public void registerForContextMenu(View view) {
741        view.setOnCreateContextMenuListener(this);
742    }
743
744    /**
745     * Prevents a context menu to be shown for the given view. This method will
746     * remove the {@link OnCreateContextMenuListener} on the view.
747     *
748     * @see #registerForContextMenu(View)
749     * @param view The view that should stop showing a context menu.
750     */
751    public void unregisterForContextMenu(View view) {
752        view.setOnCreateContextMenuListener(null);
753    }
754
755    /**
756     * This hook is called whenever an item in a context menu is selected. The
757     * default implementation simply returns false to have the normal processing
758     * happen (calling the item's Runnable or sending a message to its Handler
759     * as appropriate). You can use this method for any items for which you
760     * would like to do processing without those other facilities.
761     * <p>
762     * Use {@link MenuItem#getMenuInfo()} to get extra information set by the
763     * View that added this menu item.
764     * <p>
765     * Derived classes should call through to the base class for it to perform
766     * the default menu handling.
767     *
768     * @param item The context menu item that was selected.
769     * @return boolean Return false to allow normal context menu processing to
770     *         proceed, true to consume it here.
771     */
772    public boolean onContextItemSelected(MenuItem item) {
773        return false;
774    }
775
776    void performStop() {
777        onStop();
778        if (mStarted) {
779            mStarted = false;
780            if (mLoaderManager != null) {
781                if (mActivity == null || !mActivity.mChangingConfigurations) {
782                    mLoaderManager.doStop();
783                } else {
784                    mLoaderManager.doRetain();
785                }
786            }
787        }
788    }
789}
790