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