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