Fragment.java revision 0adacc1aa313d757ae1c517152cef838e0f35c13
1/* 2 * Copyright (C) 2011 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.support.v4.app; 18 19import android.app.Activity; 20import android.content.ComponentCallbacks; 21import android.content.Context; 22import android.content.Intent; 23import android.content.res.Configuration; 24import android.content.res.Resources; 25import android.os.Bundle; 26import android.os.Parcel; 27import android.os.Parcelable; 28import android.support.v4.util.DebugUtils; 29import android.util.AttributeSet; 30import android.util.Log; 31import android.util.SparseArray; 32import android.view.ContextMenu; 33import android.view.LayoutInflater; 34import android.view.Menu; 35import android.view.MenuInflater; 36import android.view.MenuItem; 37import android.view.View; 38import android.view.ViewGroup; 39import android.view.ContextMenu.ContextMenuInfo; 40import android.view.View.OnCreateContextMenuListener; 41import android.view.animation.Animation; 42import android.widget.AdapterView; 43 44import java.io.FileDescriptor; 45import java.io.PrintWriter; 46import java.util.HashMap; 47 48final class FragmentState implements Parcelable { 49 final String mClassName; 50 final int mIndex; 51 final boolean mFromLayout; 52 final int mFragmentId; 53 final int mContainerId; 54 final String mTag; 55 final boolean mRetainInstance; 56 final boolean mDetached; 57 final Bundle mArguments; 58 59 Bundle mSavedFragmentState; 60 61 Fragment mInstance; 62 63 public FragmentState(Fragment frag) { 64 mClassName = frag.getClass().getName(); 65 mIndex = frag.mIndex; 66 mFromLayout = frag.mFromLayout; 67 mFragmentId = frag.mFragmentId; 68 mContainerId = frag.mContainerId; 69 mTag = frag.mTag; 70 mRetainInstance = frag.mRetainInstance; 71 mDetached = frag.mDetached; 72 mArguments = frag.mArguments; 73 } 74 75 public FragmentState(Parcel in) { 76 mClassName = in.readString(); 77 mIndex = in.readInt(); 78 mFromLayout = in.readInt() != 0; 79 mFragmentId = in.readInt(); 80 mContainerId = in.readInt(); 81 mTag = in.readString(); 82 mRetainInstance = in.readInt() != 0; 83 mDetached = in.readInt() != 0; 84 mArguments = in.readBundle(); 85 mSavedFragmentState = in.readBundle(); 86 } 87 88 public Fragment instantiate(FragmentActivity activity, Fragment parent) { 89 if (mInstance != null) { 90 return mInstance; 91 } 92 93 if (mArguments != null) { 94 mArguments.setClassLoader(activity.getClassLoader()); 95 } 96 97 mInstance = Fragment.instantiate(activity, mClassName, mArguments); 98 99 if (mSavedFragmentState != null) { 100 mSavedFragmentState.setClassLoader(activity.getClassLoader()); 101 mInstance.mSavedFragmentState = mSavedFragmentState; 102 } 103 mInstance.setIndex(mIndex, parent); 104 mInstance.mFromLayout = mFromLayout; 105 mInstance.mRestored = true; 106 mInstance.mFragmentId = mFragmentId; 107 mInstance.mContainerId = mContainerId; 108 mInstance.mTag = mTag; 109 mInstance.mRetainInstance = mRetainInstance; 110 mInstance.mDetached = mDetached; 111 mInstance.mFragmentManager = activity.mFragments; 112 113 if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, 114 "Instantiated fragment " + mInstance); 115 116 return mInstance; 117 } 118 119 public int describeContents() { 120 return 0; 121 } 122 123 public void writeToParcel(Parcel dest, int flags) { 124 dest.writeString(mClassName); 125 dest.writeInt(mIndex); 126 dest.writeInt(mFromLayout ? 1 : 0); 127 dest.writeInt(mFragmentId); 128 dest.writeInt(mContainerId); 129 dest.writeString(mTag); 130 dest.writeInt(mRetainInstance ? 1 : 0); 131 dest.writeInt(mDetached ? 1 : 0); 132 dest.writeBundle(mArguments); 133 dest.writeBundle(mSavedFragmentState); 134 } 135 136 public static final Parcelable.Creator<FragmentState> CREATOR 137 = new Parcelable.Creator<FragmentState>() { 138 public FragmentState createFromParcel(Parcel in) { 139 return new FragmentState(in); 140 } 141 142 public FragmentState[] newArray(int size) { 143 return new FragmentState[size]; 144 } 145 }; 146} 147 148/** 149 * Static library support version of the framework's {@link android.app.Fragment}. 150 * Used to write apps that run on platforms prior to Android 3.0. When running 151 * on Android 3.0 or above, this implementation is still used; it does not try 152 * to switch to the framework's implementation. See the framework SDK 153 * documentation for a class overview. 154 */ 155public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener { 156 private static final HashMap<String, Class<?>> sClassMap = 157 new HashMap<String, Class<?>>(); 158 159 static final int INITIALIZING = 0; // Not yet created. 160 static final int CREATED = 1; // Created. 161 static final int ACTIVITY_CREATED = 2; // The activity has finished its creation. 162 static final int STOPPED = 3; // Fully created, not started. 163 static final int STARTED = 4; // Created and started, not resumed. 164 static final int RESUMED = 5; // Created started and resumed. 165 166 int mState = INITIALIZING; 167 168 // Non-null if the fragment's view hierarchy is currently animating away, 169 // meaning we need to wait a bit on completely destroying it. This is the 170 // view that is animating. 171 View mAnimatingAway; 172 173 // If mAnimatingAway != null, this is the state we should move to once the 174 // animation is done. 175 int mStateAfterAnimating; 176 177 // When instantiated from saved state, this is the saved state. 178 Bundle mSavedFragmentState; 179 SparseArray<Parcelable> mSavedViewState; 180 181 // Index into active fragment array. 182 int mIndex = -1; 183 184 // Internal unique name for this fragment; 185 String mWho; 186 187 // Construction arguments; 188 Bundle mArguments; 189 190 // Target fragment. 191 Fragment mTarget; 192 193 // For use when retaining a fragment: this is the index of the last mTarget. 194 int mTargetIndex = -1; 195 196 // Target request code. 197 int mTargetRequestCode; 198 199 // True if the fragment is in the list of added fragments. 200 boolean mAdded; 201 202 // If set this fragment is being removed from its activity. 203 boolean mRemoving; 204 205 // True if the fragment is in the resumed state. 206 boolean mResumed; 207 208 // Set to true if this fragment was instantiated from a layout file. 209 boolean mFromLayout; 210 211 // Set to true when the view has actually been inflated in its layout. 212 boolean mInLayout; 213 214 // True if this fragment has been restored from previously saved state. 215 boolean mRestored; 216 217 // Number of active back stack entries this fragment is in. 218 int mBackStackNesting; 219 220 // The fragment manager we are associated with. Set as soon as the 221 // fragment is used in a transaction; cleared after it has been removed 222 // from all transactions. 223 FragmentManagerImpl mFragmentManager; 224 225 // Activity this fragment is attached to. 226 FragmentActivity mActivity; 227 228 // Private fragment manager for child fragments inside of this one. 229 FragmentManagerImpl mChildFragmentManager; 230 231 // If this Fragment is contained in another Fragment, this is that container. 232 Fragment mParentFragment; 233 234 // The optional identifier for this fragment -- either the container ID if it 235 // was dynamically added to the view hierarchy, or the ID supplied in 236 // layout. 237 int mFragmentId; 238 239 // When a fragment is being dynamically added to the view hierarchy, this 240 // is the identifier of the parent container it is being added to. 241 int mContainerId; 242 243 // The optional named tag for this fragment -- usually used to find 244 // fragments that are not part of the layout. 245 String mTag; 246 247 // Set to true when the app has requested that this fragment be hidden 248 // from the user. 249 boolean mHidden; 250 251 // Set to true when the app has requested that this fragment be deactivated. 252 boolean mDetached; 253 254 // If set this fragment would like its instance retained across 255 // configuration changes. 256 boolean mRetainInstance; 257 258 // If set this fragment is being retained across the current config change. 259 boolean mRetaining; 260 261 // If set this fragment has menu items to contribute. 262 boolean mHasMenu; 263 264 // Set to true to allow the fragment's menu to be shown. 265 boolean mMenuVisible = true; 266 267 // Used to verify that subclasses call through to super class. 268 boolean mCalled; 269 270 // If app has requested a specific animation, this is the one to use. 271 int mNextAnim; 272 273 // The parent container of the fragment after dynamically added to UI. 274 ViewGroup mContainer; 275 276 // The View generated for this fragment. 277 View mView; 278 279 // The real inner view that will save/restore state. 280 View mInnerView; 281 282 // Whether this fragment should defer starting until after other fragments 283 // have been started and their loaders are finished. 284 boolean mDeferStart; 285 286 // Hint provided by the app that this fragment is currently visible to the user. 287 boolean mUserVisibleHint = true; 288 289 LoaderManagerImpl mLoaderManager; 290 boolean mLoadersStarted; 291 boolean mCheckedForLoaderManager; 292 293 /** 294 * State information that has been retrieved from a fragment instance 295 * through {@link FragmentManager#saveFragmentInstanceState(Fragment) 296 * FragmentManager.saveFragmentInstanceState}. 297 */ 298 public static class SavedState implements Parcelable { 299 final Bundle mState; 300 301 SavedState(Bundle state) { 302 mState = state; 303 } 304 305 SavedState(Parcel in, ClassLoader loader) { 306 mState = in.readBundle(); 307 if (loader != null && mState != null) { 308 mState.setClassLoader(loader); 309 } 310 } 311 312 @Override 313 public int describeContents() { 314 return 0; 315 } 316 317 @Override 318 public void writeToParcel(Parcel dest, int flags) { 319 dest.writeBundle(mState); 320 } 321 322 public static final Parcelable.Creator<SavedState> CREATOR 323 = new Parcelable.Creator<SavedState>() { 324 public SavedState createFromParcel(Parcel in) { 325 return new SavedState(in, null); 326 } 327 328 public SavedState[] newArray(int size) { 329 return new SavedState[size]; 330 } 331 }; 332 } 333 334 /** 335 * Thrown by {@link Fragment#instantiate(Context, String, Bundle)} when 336 * there is an instantiation failure. 337 */ 338 static public class InstantiationException extends RuntimeException { 339 public InstantiationException(String msg, Exception cause) { 340 super(msg, cause); 341 } 342 } 343 344 /** 345 * Default constructor. <strong>Every</strong> fragment must have an 346 * empty constructor, so it can be instantiated when restoring its 347 * activity's state. It is strongly recommended that subclasses do not 348 * have other constructors with parameters, since these constructors 349 * will not be called when the fragment is re-instantiated; instead, 350 * arguments can be supplied by the caller with {@link #setArguments} 351 * and later retrieved by the Fragment with {@link #getArguments}. 352 * 353 * <p>Applications should generally not implement a constructor. The 354 * first place application code an run where the fragment is ready to 355 * be used is in {@link #onAttach(Activity)}, the point where the fragment 356 * is actually associated with its activity. Some applications may also 357 * want to implement {@link #onInflate} to retrieve attributes from a 358 * layout resource, though should take care here because this happens for 359 * the fragment is attached to its activity. 360 */ 361 public Fragment() { 362 } 363 364 /** 365 * Like {@link #instantiate(Context, String, Bundle)} but with a null 366 * argument Bundle. 367 */ 368 public static Fragment instantiate(Context context, String fname) { 369 return instantiate(context, fname, null); 370 } 371 372 /** 373 * Create a new instance of a Fragment with the given class name. This is 374 * the same as calling its empty constructor. 375 * 376 * @param context The calling context being used to instantiate the fragment. 377 * This is currently just used to get its ClassLoader. 378 * @param fname The class name of the fragment to instantiate. 379 * @param args Bundle of arguments to supply to the fragment, which it 380 * can retrieve with {@link #getArguments()}. May be null. 381 * @return Returns a new fragment instance. 382 * @throws InstantiationException If there is a failure in instantiating 383 * the given fragment class. This is a runtime exception; it is not 384 * normally expected to happen. 385 */ 386 public static Fragment instantiate(Context context, String fname, Bundle args) { 387 try { 388 Class<?> clazz = sClassMap.get(fname); 389 if (clazz == null) { 390 // Class not found in the cache, see if it's real, and try to add it 391 clazz = context.getClassLoader().loadClass(fname); 392 sClassMap.put(fname, clazz); 393 } 394 Fragment f = (Fragment)clazz.newInstance(); 395 if (args != null) { 396 args.setClassLoader(f.getClass().getClassLoader()); 397 f.mArguments = args; 398 } 399 return f; 400 } catch (ClassNotFoundException e) { 401 throw new InstantiationException("Unable to instantiate fragment " + fname 402 + ": make sure class name exists, is public, and has an" 403 + " empty constructor that is public", e); 404 } catch (java.lang.InstantiationException e) { 405 throw new InstantiationException("Unable to instantiate fragment " + fname 406 + ": make sure class name exists, is public, and has an" 407 + " empty constructor that is public", e); 408 } catch (IllegalAccessException e) { 409 throw new InstantiationException("Unable to instantiate fragment " + fname 410 + ": make sure class name exists, is public, and has an" 411 + " empty constructor that is public", e); 412 } 413 } 414 415 final void restoreViewState(Bundle savedInstanceState) { 416 if (mSavedViewState != null) { 417 mInnerView.restoreHierarchyState(mSavedViewState); 418 mSavedViewState = null; 419 } 420 mCalled = false; 421 onViewStateRestored(savedInstanceState); 422 if (!mCalled) { 423 throw new SuperNotCalledException("Fragment " + this 424 + " did not call through to super.onViewStateRestored()"); 425 } 426 } 427 428 final void setIndex(int index, Fragment parent) { 429 mIndex = index; 430 if (parent != null) { 431 mWho = parent.mWho + ":" + mIndex; 432 } else { 433 mWho = "android:fragment:" + mIndex; 434 } 435 } 436 437 final boolean isInBackStack() { 438 return mBackStackNesting > 0; 439 } 440 441 /** 442 * Subclasses can not override equals(). 443 */ 444 @Override final public boolean equals(Object o) { 445 return super.equals(o); 446 } 447 448 /** 449 * Subclasses can not override hashCode(). 450 */ 451 @Override final public int hashCode() { 452 return super.hashCode(); 453 } 454 455 @Override 456 public String toString() { 457 StringBuilder sb = new StringBuilder(128); 458 DebugUtils.buildShortClassTag(this, sb); 459 if (mIndex >= 0) { 460 sb.append(" #"); 461 sb.append(mIndex); 462 } 463 if (mFragmentId != 0) { 464 sb.append(" id=0x"); 465 sb.append(Integer.toHexString(mFragmentId)); 466 } 467 if (mTag != null) { 468 sb.append(" "); 469 sb.append(mTag); 470 } 471 sb.append('}'); 472 return sb.toString(); 473 } 474 475 /** 476 * Return the identifier this fragment is known by. This is either 477 * the android:id value supplied in a layout or the container view ID 478 * supplied when adding the fragment. 479 */ 480 final public int getId() { 481 return mFragmentId; 482 } 483 484 /** 485 * Get the tag name of the fragment, if specified. 486 */ 487 final public String getTag() { 488 return mTag; 489 } 490 491 /** 492 * Supply the construction arguments for this fragment. This can only 493 * be called before the fragment has been attached to its activity; that 494 * is, you should call it immediately after constructing the fragment. The 495 * arguments supplied here will be retained across fragment destroy and 496 * creation. 497 */ 498 public void setArguments(Bundle args) { 499 if (mIndex >= 0) { 500 throw new IllegalStateException("Fragment already active"); 501 } 502 mArguments = args; 503 } 504 505 /** 506 * Return the arguments supplied when the fragment was instantiated, 507 * if any. 508 */ 509 final public Bundle getArguments() { 510 return mArguments; 511 } 512 513 /** 514 * Set the initial saved state that this Fragment should restore itself 515 * from when first being constructed, as returned by 516 * {@link FragmentManager#saveFragmentInstanceState(Fragment) 517 * FragmentManager.saveFragmentInstanceState}. 518 * 519 * @param state The state the fragment should be restored from. 520 */ 521 public void setInitialSavedState(SavedState state) { 522 if (mIndex >= 0) { 523 throw new IllegalStateException("Fragment already active"); 524 } 525 mSavedFragmentState = state != null && state.mState != null 526 ? state.mState : null; 527 } 528 529 /** 530 * Optional target for this fragment. This may be used, for example, 531 * if this fragment is being started by another, and when done wants to 532 * give a result back to the first. The target set here is retained 533 * across instances via {@link FragmentManager#putFragment 534 * FragmentManager.putFragment()}. 535 * 536 * @param fragment The fragment that is the target of this one. 537 * @param requestCode Optional request code, for convenience if you 538 * are going to call back with {@link #onActivityResult(int, int, Intent)}. 539 */ 540 public void setTargetFragment(Fragment fragment, int requestCode) { 541 mTarget = fragment; 542 mTargetRequestCode = requestCode; 543 } 544 545 /** 546 * Return the target fragment set by {@link #setTargetFragment}. 547 */ 548 final public Fragment getTargetFragment() { 549 return mTarget; 550 } 551 552 /** 553 * Return the target request code set by {@link #setTargetFragment}. 554 */ 555 final public int getTargetRequestCode() { 556 return mTargetRequestCode; 557 } 558 559 /** 560 * Return the Activity this fragment is currently associated with. 561 */ 562 final public FragmentActivity getActivity() { 563 return mActivity; 564 } 565 566 /** 567 * Return <code>getActivity().getResources()</code>. 568 */ 569 final public Resources getResources() { 570 if (mActivity == null) { 571 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 572 } 573 return mActivity.getResources(); 574 } 575 576 /** 577 * Return a localized, styled CharSequence from the application's package's 578 * default string table. 579 * 580 * @param resId Resource id for the CharSequence text 581 */ 582 public final CharSequence getText(int resId) { 583 return getResources().getText(resId); 584 } 585 586 /** 587 * Return a localized string from the application's package's 588 * default string table. 589 * 590 * @param resId Resource id for the string 591 */ 592 public final String getString(int resId) { 593 return getResources().getString(resId); 594 } 595 596 /** 597 * Return a localized formatted string from the application's package's 598 * default string table, substituting the format arguments as defined in 599 * {@link java.util.Formatter} and {@link java.lang.String#format}. 600 * 601 * @param resId Resource id for the format string 602 * @param formatArgs The format arguments that will be used for substitution. 603 */ 604 605 public final String getString(int resId, Object... formatArgs) { 606 return getResources().getString(resId, formatArgs); 607 } 608 609 /** 610 * Return the FragmentManager for interacting with fragments associated 611 * with this fragment's activity. Note that this will be non-null slightly 612 * before {@link #getActivity()}, during the time from when the fragment is 613 * placed in a {@link FragmentTransaction} until it is committed and 614 * attached to its activity. 615 * 616 * <p>If this Fragment is a child of another Fragment, the FragmentManager 617 * returned here will be the parent's {@link #getChildFragmentManager()}. 618 */ 619 final public FragmentManager getFragmentManager() { 620 return mFragmentManager; 621 } 622 623 /** 624 * Return a private FragmentManager for placing and managing Fragments 625 * inside of this Fragment. 626 */ 627 final public FragmentManager getChildFragmentManager() { 628 if (mChildFragmentManager == null) { 629 instantiateChildFragmentManager(); 630 if (mState >= RESUMED) { 631 mChildFragmentManager.dispatchResume(); 632 } else if (mState >= STARTED) { 633 mChildFragmentManager.dispatchStart(); 634 } else if (mState >= ACTIVITY_CREATED) { 635 mChildFragmentManager.dispatchActivityCreated(); 636 } else if (mState >= CREATED) { 637 mChildFragmentManager.dispatchCreate(); 638 } 639 } 640 return mChildFragmentManager; 641 } 642 643 /** 644 * Returns the parent Fragment containing this Fragment. If this Fragment 645 * is attached directly to an Activity, returns null. 646 */ 647 final public Fragment getParentFragment() { 648 return mParentFragment; 649 } 650 651 /** 652 * Return true if the fragment is currently added to its activity. 653 */ 654 final public boolean isAdded() { 655 return mActivity != null && mAdded; 656 } 657 658 /** 659 * Return true if the fragment has been explicitly detached from the UI. 660 * That is, {@link FragmentTransaction#detach(Fragment) 661 * FragmentTransaction.detach(Fragment)} has been used on it. 662 */ 663 final public boolean isDetached() { 664 return mDetached; 665 } 666 667 /** 668 * Return true if this fragment is currently being removed from its 669 * activity. This is <em>not</em> whether its activity is finishing, but 670 * rather whether it is in the process of being removed from its activity. 671 */ 672 final public boolean isRemoving() { 673 return mRemoving; 674 } 675 676 /** 677 * Return true if the layout is included as part of an activity view 678 * hierarchy via the <fragment> tag. This will always be true when 679 * fragments are created through the <fragment> tag, <em>except</em> 680 * in the case where an old fragment is restored from a previous state and 681 * it does not appear in the layout of the current state. 682 */ 683 final public boolean isInLayout() { 684 return mInLayout; 685 } 686 687 /** 688 * Return true if the fragment is in the resumed state. This is true 689 * for the duration of {@link #onResume()} and {@link #onPause()} as well. 690 */ 691 final public boolean isResumed() { 692 return mResumed; 693 } 694 695 /** 696 * Return true if the fragment is currently visible to the user. This means 697 * it: (1) has been added, (2) has its view attached to the window, and 698 * (3) is not hidden. 699 */ 700 final public boolean isVisible() { 701 return isAdded() && !isHidden() && mView != null 702 && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE; 703 } 704 705 /** 706 * Return true if the fragment has been hidden. By default fragments 707 * are shown. You can find out about changes to this state with 708 * {@link #onHiddenChanged}. Note that the hidden state is orthogonal 709 * to other states -- that is, to be visible to the user, a fragment 710 * must be both started and not hidden. 711 */ 712 final public boolean isHidden() { 713 return mHidden; 714 } 715 716 /** 717 * Called when the hidden state (as returned by {@link #isHidden()} of 718 * the fragment has changed. Fragments start out not hidden; this will 719 * be called whenever the fragment changes state from that. 720 * @param hidden True if the fragment is now hidden, false if it is not 721 * visible. 722 */ 723 public void onHiddenChanged(boolean hidden) { 724 } 725 726 /** 727 * Control whether a fragment instance is retained across Activity 728 * re-creation (such as from a configuration change). This can only 729 * be used with fragments not in the back stack. If set, the fragment 730 * lifecycle will be slightly different when an activity is recreated: 731 * <ul> 732 * <li> {@link #onDestroy()} will not be called (but {@link #onDetach()} still 733 * will be, because the fragment is being detached from its current activity). 734 * <li> {@link #onCreate(Bundle)} will not be called since the fragment 735 * is not being re-created. 736 * <li> {@link #onAttach(Activity)} and {@link #onActivityCreated(Bundle)} <b>will</b> 737 * still be called. 738 * </ul> 739 */ 740 public void setRetainInstance(boolean retain) { 741 if (retain && mParentFragment != null) { 742 throw new IllegalStateException( 743 "Can't retain fragements that are nested in other fragments"); 744 } 745 mRetainInstance = retain; 746 } 747 748 final public boolean getRetainInstance() { 749 return mRetainInstance; 750 } 751 752 /** 753 * Report that this fragment would like to participate in populating 754 * the options menu by receiving a call to {@link #onCreateOptionsMenu} 755 * and related methods. 756 * 757 * @param hasMenu If true, the fragment has menu items to contribute. 758 */ 759 public void setHasOptionsMenu(boolean hasMenu) { 760 if (mHasMenu != hasMenu) { 761 mHasMenu = hasMenu; 762 if (isAdded() && !isHidden()) { 763 mActivity.supportInvalidateOptionsMenu(); 764 } 765 } 766 } 767 768 /** 769 * Set a hint for whether this fragment's menu should be visible. This 770 * is useful if you know that a fragment has been placed in your view 771 * hierarchy so that the user can not currently seen it, so any menu items 772 * it has should also not be shown. 773 * 774 * @param menuVisible The default is true, meaning the fragment's menu will 775 * be shown as usual. If false, the user will not see the menu. 776 */ 777 public void setMenuVisibility(boolean menuVisible) { 778 if (mMenuVisible != menuVisible) { 779 mMenuVisible = menuVisible; 780 if (mHasMenu && isAdded() && !isHidden()) { 781 mActivity.supportInvalidateOptionsMenu(); 782 } 783 } 784 } 785 786 /** 787 * Set a hint to the system about whether this fragment's UI is currently visible 788 * to the user. This hint defaults to true and is persistent across fragment instance 789 * state save and restore. 790 * 791 * <p>An app may set this to false to indicate that the fragment's UI is 792 * scrolled out of visibility or is otherwise not directly visible to the user. 793 * This may be used by the system to prioritize operations such as fragment lifecycle updates 794 * or loader ordering behavior.</p> 795 * 796 * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default), 797 * false if it is not. 798 */ 799 public void setUserVisibleHint(boolean isVisibleToUser) { 800 if (!mUserVisibleHint && isVisibleToUser && mState < STARTED) { 801 mFragmentManager.performPendingDeferredStart(this); 802 } 803 mUserVisibleHint = isVisibleToUser; 804 mDeferStart = !isVisibleToUser; 805 } 806 807 /** 808 * @return The current value of the user-visible hint on this fragment. 809 * @see #setUserVisibleHint(boolean) 810 */ 811 public boolean getUserVisibleHint() { 812 return mUserVisibleHint; 813 } 814 815 /** 816 * Return the LoaderManager for this fragment, creating it if needed. 817 */ 818 public LoaderManager getLoaderManager() { 819 if (mLoaderManager != null) { 820 return mLoaderManager; 821 } 822 if (mActivity == null) { 823 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 824 } 825 mCheckedForLoaderManager = true; 826 mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, true); 827 return mLoaderManager; 828 } 829 830 /** 831 * Call {@link Activity#startActivity(Intent)} on the fragment's 832 * containing Activity. 833 */ 834 public void startActivity(Intent intent) { 835 if (mActivity == null) { 836 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 837 } 838 mActivity.startActivityFromFragment(this, intent, -1); 839 } 840 841 /** 842 * Call {@link Activity#startActivityForResult(Intent, int)} on the fragment's 843 * containing Activity. 844 */ 845 public void startActivityForResult(Intent intent, int requestCode) { 846 if (mActivity == null) { 847 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 848 } 849 mActivity.startActivityFromFragment(this, intent, requestCode); 850 } 851 852 /** 853 * Receive the result from a previous call to 854 * {@link #startActivityForResult(Intent, int)}. This follows the 855 * related Activity API as described there in 856 * {@link Activity#onActivityResult(int, int, Intent)}. 857 * 858 * @param requestCode The integer request code originally supplied to 859 * startActivityForResult(), allowing you to identify who this 860 * result came from. 861 * @param resultCode The integer result code returned by the child activity 862 * through its setResult(). 863 * @param data An Intent, which can return result data to the caller 864 * (various data can be attached to Intent "extras"). 865 */ 866 public void onActivityResult(int requestCode, int resultCode, Intent data) { 867 } 868 869 /** 870 * @hide Hack so that DialogFragment can make its Dialog before creating 871 * its views, and the view construction can use the dialog's context for 872 * inflation. Maybe this should become a public API. Note sure. 873 */ 874 public LayoutInflater getLayoutInflater(Bundle savedInstanceState) { 875 return mActivity.getLayoutInflater(); 876 } 877 878 /** 879 * Called when a fragment is being created as part of a view layout 880 * inflation, typically from setting the content view of an activity. This 881 * may be called immediately after the fragment is created from a <fragment> 882 * tag in a layout file. Note this is <em>before</em> the fragment's 883 * {@link #onAttach(Activity)} has been called; all you should do here is 884 * parse the attributes and save them away. 885 * 886 * <p>This is called every time the fragment is inflated, even if it is 887 * being inflated into a new instance with saved state. It typically makes 888 * sense to re-parse the parameters each time, to allow them to change with 889 * different configurations.</p> 890 * 891 * <p>Here is a typical implementation of a fragment that can take parameters 892 * both through attributes supplied here as well from {@link #getArguments()}:</p> 893 * 894 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java 895 * fragment} 896 * 897 * <p>Note that parsing the XML attributes uses a "styleable" resource. The 898 * declaration for the styleable used here is:</p> 899 * 900 * {@sample development/samples/ApiDemos/res/values/attrs.xml fragment_arguments} 901 * 902 * <p>The fragment can then be declared within its activity's content layout 903 * through a tag like this:</p> 904 * 905 * {@sample development/samples/ApiDemos/res/layout/fragment_arguments.xml from_attributes} 906 * 907 * <p>This fragment can also be created dynamically from arguments given 908 * at runtime in the arguments Bundle; here is an example of doing so at 909 * creation of the containing activity:</p> 910 * 911 * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java 912 * create} 913 * 914 * @param activity The Activity that is inflating this fragment. 915 * @param attrs The attributes at the tag where the fragment is 916 * being created. 917 * @param savedInstanceState If the fragment is being re-created from 918 * a previous saved state, this is the state. 919 */ 920 public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) { 921 mCalled = true; 922 } 923 924 /** 925 * Called when a fragment is first attached to its activity. 926 * {@link #onCreate(Bundle)} will be called after this. 927 */ 928 public void onAttach(Activity activity) { 929 mCalled = true; 930 } 931 932 /** 933 * Called when a fragment loads an animation. 934 */ 935 public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { 936 return null; 937 } 938 939 /** 940 * Called to do initial creation of a fragment. This is called after 941 * {@link #onAttach(Activity)} and before 942 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. 943 * 944 * <p>Note that this can be called while the fragment's activity is 945 * still in the process of being created. As such, you can not rely 946 * on things like the activity's content view hierarchy being initialized 947 * at this point. If you want to do work once the activity itself is 948 * created, see {@link #onActivityCreated(Bundle)}. 949 * 950 * @param savedInstanceState If the fragment is being re-created from 951 * a previous saved state, this is the state. 952 */ 953 public void onCreate(Bundle savedInstanceState) { 954 mCalled = true; 955 } 956 957 /** 958 * Called to have the fragment instantiate its user interface view. 959 * This is optional, and non-graphical fragments can return null (which 960 * is the default implementation). This will be called between 961 * {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}. 962 * 963 * <p>If you return a View from here, you will later be called in 964 * {@link #onDestroyView} when the view is being released. 965 * 966 * @param inflater The LayoutInflater object that can be used to inflate 967 * any views in the fragment, 968 * @param container If non-null, this is the parent view that the fragment's 969 * UI should be attached to. The fragment should not add the view itself, 970 * but this can be used to generate the LayoutParams of the view. 971 * @param savedInstanceState If non-null, this fragment is being re-constructed 972 * from a previous saved state as given here. 973 * 974 * @return Return the View for the fragment's UI, or null. 975 */ 976 public View onCreateView(LayoutInflater inflater, ViewGroup container, 977 Bundle savedInstanceState) { 978 return null; 979 } 980 981 /** 982 * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} 983 * has returned, but before any saved state has been restored in to the view. 984 * This gives subclasses a chance to initialize themselves once 985 * they know their view hierarchy has been completely created. The fragment's 986 * view hierarchy is not however attached to its parent at this point. 987 * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. 988 * @param savedInstanceState If non-null, this fragment is being re-constructed 989 * from a previous saved state as given here. 990 */ 991 public void onViewCreated(View view, Bundle savedInstanceState) { 992 } 993 994 /** 995 * Get the root view for the fragment's layout (the one returned by {@link #onCreateView}), 996 * if provided. 997 * 998 * @return The fragment's root view, or null if it has no layout. 999 */ 1000 public View getView() { 1001 return mView; 1002 } 1003 1004 /** 1005 * Called when the fragment's activity has been created and this 1006 * fragment's view hierarchy instantiated. It can be used to do final 1007 * initialization once these pieces are in place, such as retrieving 1008 * views or restoring state. It is also useful for fragments that use 1009 * {@link #setRetainInstance(boolean)} to retain their instance, 1010 * as this callback tells the fragment when it is fully associated with 1011 * the new activity instance. This is called after {@link #onCreateView} 1012 * and before {@link #onViewStateRestored(Bundle)}. 1013 * 1014 * @param savedInstanceState If the fragment is being re-created from 1015 * a previous saved state, this is the state. 1016 */ 1017 public void onActivityCreated(Bundle savedInstanceState) { 1018 mCalled = true; 1019 } 1020 1021 /** 1022 * Called when all saved state has been restored into the view hierarchy 1023 * of the fragment. This can be used to do initialization based on saved 1024 * state that you are letting the view hierarchy track itself, such as 1025 * whether check box widgets are currently checked. This is called 1026 * after {@link #onActivityCreated(Bundle)} and before 1027 * {@link #onStart()}. 1028 * 1029 * @param savedInstanceState If the fragment is being re-created from 1030 * a previous saved state, this is the state. 1031 */ 1032 public void onViewStateRestored(Bundle savedInstanceState) { 1033 mCalled = true; 1034 } 1035 1036 /** 1037 * Called when the Fragment is visible to the user. This is generally 1038 * tied to {@link Activity#onStart() Activity.onStart} of the containing 1039 * Activity's lifecycle. 1040 */ 1041 public void onStart() { 1042 mCalled = true; 1043 1044 if (!mLoadersStarted) { 1045 mLoadersStarted = true; 1046 if (!mCheckedForLoaderManager) { 1047 mCheckedForLoaderManager = true; 1048 mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false); 1049 } 1050 if (mLoaderManager != null) { 1051 mLoaderManager.doStart(); 1052 } 1053 } 1054 } 1055 1056 /** 1057 * Called when the fragment is visible to the user and actively running. 1058 * This is generally 1059 * tied to {@link Activity#onResume() Activity.onResume} of the containing 1060 * Activity's lifecycle. 1061 */ 1062 public void onResume() { 1063 mCalled = true; 1064 } 1065 1066 /** 1067 * Called to ask the fragment to save its current dynamic state, so it 1068 * can later be reconstructed in a new instance of its process is 1069 * restarted. If a new instance of the fragment later needs to be 1070 * created, the data you place in the Bundle here will be available 1071 * in the Bundle given to {@link #onCreate(Bundle)}, 1072 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}, and 1073 * {@link #onActivityCreated(Bundle)}. 1074 * 1075 * <p>This corresponds to {@link Activity#onSaveInstanceState(Bundle) 1076 * Activity.onSaveInstanceState(Bundle)} and most of the discussion there 1077 * applies here as well. Note however: <em>this method may be called 1078 * at any time before {@link #onDestroy()}</em>. There are many situations 1079 * where a fragment may be mostly torn down (such as when placed on the 1080 * back stack with no UI showing), but its state will not be saved until 1081 * its owning activity actually needs to save its state. 1082 * 1083 * @param outState Bundle in which to place your saved state. 1084 */ 1085 public void onSaveInstanceState(Bundle outState) { 1086 } 1087 1088 public void onConfigurationChanged(Configuration newConfig) { 1089 mCalled = true; 1090 } 1091 1092 /** 1093 * Called when the Fragment is no longer resumed. This is generally 1094 * tied to {@link Activity#onPause() Activity.onPause} of the containing 1095 * Activity's lifecycle. 1096 */ 1097 public void onPause() { 1098 mCalled = true; 1099 } 1100 1101 /** 1102 * Called when the Fragment is no longer started. This is generally 1103 * tied to {@link Activity#onStop() Activity.onStop} of the containing 1104 * Activity's lifecycle. 1105 */ 1106 public void onStop() { 1107 mCalled = true; 1108 } 1109 1110 public void onLowMemory() { 1111 mCalled = true; 1112 } 1113 1114 /** 1115 * Called when the view previously created by {@link #onCreateView} has 1116 * been detached from the fragment. The next time the fragment needs 1117 * to be displayed, a new view will be created. This is called 1118 * after {@link #onStop()} and before {@link #onDestroy()}. It is called 1119 * <em>regardless</em> of whether {@link #onCreateView} returned a 1120 * non-null view. Internally it is called after the view's state has 1121 * been saved but before it has been removed from its parent. 1122 */ 1123 public void onDestroyView() { 1124 mCalled = true; 1125 } 1126 1127 /** 1128 * Called when the fragment is no longer in use. This is called 1129 * after {@link #onStop()} and before {@link #onDetach()}. 1130 */ 1131 public void onDestroy() { 1132 mCalled = true; 1133 //Log.v("foo", "onDestroy: mCheckedForLoaderManager=" + mCheckedForLoaderManager 1134 // + " mLoaderManager=" + mLoaderManager); 1135 if (!mCheckedForLoaderManager) { 1136 mCheckedForLoaderManager = true; 1137 mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false); 1138 } 1139 if (mLoaderManager != null) { 1140 mLoaderManager.doDestroy(); 1141 } 1142 } 1143 1144 /** 1145 * Called by the fragment manager once this fragment has been removed, 1146 * so that we don't have any left-over state if the application decides 1147 * to re-use the instance. This only clears state that the framework 1148 * internally manages, not things the application sets. 1149 */ 1150 void initState() { 1151 mIndex = -1; 1152 mWho = null; 1153 mAdded = false; 1154 mRemoving = false; 1155 mResumed = false; 1156 mFromLayout = false; 1157 mInLayout = false; 1158 mRestored = false; 1159 mBackStackNesting = 0; 1160 mFragmentManager = null; 1161 mActivity = null; 1162 mFragmentId = 0; 1163 mContainerId = 0; 1164 mTag = null; 1165 mHidden = false; 1166 mDetached = false; 1167 mRetaining = false; 1168 mLoaderManager = null; 1169 mLoadersStarted = false; 1170 mCheckedForLoaderManager = false; 1171 } 1172 1173 /** 1174 * Called when the fragment is no longer attached to its activity. This 1175 * is called after {@link #onDestroy()}. 1176 */ 1177 public void onDetach() { 1178 mCalled = true; 1179 } 1180 1181 /** 1182 * Initialize the contents of the Activity's standard options menu. You 1183 * should place your menu items in to <var>menu</var>. For this method 1184 * to be called, you must have first called {@link #setHasOptionsMenu}. See 1185 * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu} 1186 * for more information. 1187 * 1188 * @param menu The options menu in which you place your items. 1189 * 1190 * @see #setHasOptionsMenu 1191 * @see #onPrepareOptionsMenu 1192 * @see #onOptionsItemSelected 1193 */ 1194 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 1195 } 1196 1197 /** 1198 * Prepare the Screen's standard options menu to be displayed. This is 1199 * called right before the menu is shown, every time it is shown. You can 1200 * use this method to efficiently enable/disable items or otherwise 1201 * dynamically modify the contents. See 1202 * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu} 1203 * for more information. 1204 * 1205 * @param menu The options menu as last shown or first initialized by 1206 * onCreateOptionsMenu(). 1207 * 1208 * @see #setHasOptionsMenu 1209 * @see #onCreateOptionsMenu 1210 */ 1211 public void onPrepareOptionsMenu(Menu menu) { 1212 } 1213 1214 /** 1215 * Called when this fragment's option menu items are no longer being 1216 * included in the overall options menu. Receiving this call means that 1217 * the menu needed to be rebuilt, but this fragment's items were not 1218 * included in the newly built menu (its {@link #onCreateOptionsMenu(Menu, MenuInflater)} 1219 * was not called). 1220 */ 1221 public void onDestroyOptionsMenu() { 1222 } 1223 1224 /** 1225 * This hook is called whenever an item in your options menu is selected. 1226 * The default implementation simply returns false to have the normal 1227 * processing happen (calling the item's Runnable or sending a message to 1228 * its Handler as appropriate). You can use this method for any items 1229 * for which you would like to do processing without those other 1230 * facilities. 1231 * 1232 * <p>Derived classes should call through to the base class for it to 1233 * perform the default menu handling. 1234 * 1235 * @param item The menu item that was selected. 1236 * 1237 * @return boolean Return false to allow normal menu processing to 1238 * proceed, true to consume it here. 1239 * 1240 * @see #onCreateOptionsMenu 1241 */ 1242 public boolean onOptionsItemSelected(MenuItem item) { 1243 return false; 1244 } 1245 1246 /** 1247 * This hook is called whenever the options menu is being closed (either by the user canceling 1248 * the menu with the back/menu button, or when an item is selected). 1249 * 1250 * @param menu The options menu as last shown or first initialized by 1251 * onCreateOptionsMenu(). 1252 */ 1253 public void onOptionsMenuClosed(Menu menu) { 1254 } 1255 1256 /** 1257 * Called when a context menu for the {@code view} is about to be shown. 1258 * Unlike {@link #onCreateOptionsMenu}, this will be called every 1259 * time the context menu is about to be shown and should be populated for 1260 * the view (or item inside the view for {@link AdapterView} subclasses, 1261 * this can be found in the {@code menuInfo})). 1262 * <p> 1263 * Use {@link #onContextItemSelected(android.view.MenuItem)} to know when an 1264 * item has been selected. 1265 * <p> 1266 * The default implementation calls up to 1267 * {@link Activity#onCreateContextMenu Activity.onCreateContextMenu}, though 1268 * you can not call this implementation if you don't want that behavior. 1269 * <p> 1270 * It is not safe to hold onto the context menu after this method returns. 1271 * {@inheritDoc} 1272 */ 1273 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 1274 getActivity().onCreateContextMenu(menu, v, menuInfo); 1275 } 1276 1277 /** 1278 * Registers a context menu to be shown for the given view (multiple views 1279 * can show the context menu). This method will set the 1280 * {@link OnCreateContextMenuListener} on the view to this fragment, so 1281 * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be 1282 * called when it is time to show the context menu. 1283 * 1284 * @see #unregisterForContextMenu(View) 1285 * @param view The view that should show a context menu. 1286 */ 1287 public void registerForContextMenu(View view) { 1288 view.setOnCreateContextMenuListener(this); 1289 } 1290 1291 /** 1292 * Prevents a context menu to be shown for the given view. This method will 1293 * remove the {@link OnCreateContextMenuListener} on the view. 1294 * 1295 * @see #registerForContextMenu(View) 1296 * @param view The view that should stop showing a context menu. 1297 */ 1298 public void unregisterForContextMenu(View view) { 1299 view.setOnCreateContextMenuListener(null); 1300 } 1301 1302 /** 1303 * This hook is called whenever an item in a context menu is selected. The 1304 * default implementation simply returns false to have the normal processing 1305 * happen (calling the item's Runnable or sending a message to its Handler 1306 * as appropriate). You can use this method for any items for which you 1307 * would like to do processing without those other facilities. 1308 * <p> 1309 * Use {@link MenuItem#getMenuInfo()} to get extra information set by the 1310 * View that added this menu item. 1311 * <p> 1312 * Derived classes should call through to the base class for it to perform 1313 * the default menu handling. 1314 * 1315 * @param item The context menu item that was selected. 1316 * @return boolean Return false to allow normal context menu processing to 1317 * proceed, true to consume it here. 1318 */ 1319 public boolean onContextItemSelected(MenuItem item) { 1320 return false; 1321 } 1322 1323 /** 1324 * Print the Fragments's state into the given stream. 1325 * 1326 * @param prefix Text to print at the front of each line. 1327 * @param fd The raw file descriptor that the dump is being sent to. 1328 * @param writer The PrintWriter to which you should dump your state. This will be 1329 * closed for you after you return. 1330 * @param args additional arguments to the dump request. 1331 */ 1332 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 1333 writer.print(prefix); writer.print("mFragmentId=#"); 1334 writer.print(Integer.toHexString(mFragmentId)); 1335 writer.print(" mContainerId=#"); 1336 writer.print(Integer.toHexString(mContainerId)); 1337 writer.print(" mTag="); writer.println(mTag); 1338 writer.print(prefix); writer.print("mState="); writer.print(mState); 1339 writer.print(" mIndex="); writer.print(mIndex); 1340 writer.print(" mWho="); writer.print(mWho); 1341 writer.print(" mBackStackNesting="); writer.println(mBackStackNesting); 1342 writer.print(prefix); writer.print("mAdded="); writer.print(mAdded); 1343 writer.print(" mRemoving="); writer.print(mRemoving); 1344 writer.print(" mResumed="); writer.print(mResumed); 1345 writer.print(" mFromLayout="); writer.print(mFromLayout); 1346 writer.print(" mInLayout="); writer.println(mInLayout); 1347 writer.print(prefix); writer.print("mHidden="); writer.print(mHidden); 1348 writer.print(" mDetached="); writer.print(mDetached); 1349 writer.print(" mMenuVisible="); writer.print(mMenuVisible); 1350 writer.print(" mHasMenu="); writer.println(mHasMenu); 1351 writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance); 1352 writer.print(" mRetaining="); writer.print(mRetaining); 1353 writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint); 1354 if (mFragmentManager != null) { 1355 writer.print(prefix); writer.print("mFragmentManager="); 1356 writer.println(mFragmentManager); 1357 } 1358 if (mActivity != null) { 1359 writer.print(prefix); writer.print("mActivity="); 1360 writer.println(mActivity); 1361 } 1362 if (mParentFragment != null) { 1363 writer.print(prefix); writer.print("mParentFragment="); 1364 writer.println(mParentFragment); 1365 } 1366 if (mArguments != null) { 1367 writer.print(prefix); writer.print("mArguments="); writer.println(mArguments); 1368 } 1369 if (mSavedFragmentState != null) { 1370 writer.print(prefix); writer.print("mSavedFragmentState="); 1371 writer.println(mSavedFragmentState); 1372 } 1373 if (mSavedViewState != null) { 1374 writer.print(prefix); writer.print("mSavedViewState="); 1375 writer.println(mSavedViewState); 1376 } 1377 if (mTarget != null) { 1378 writer.print(prefix); writer.print("mTarget="); writer.print(mTarget); 1379 writer.print(" mTargetRequestCode="); 1380 writer.println(mTargetRequestCode); 1381 } 1382 if (mNextAnim != 0) { 1383 writer.print(prefix); writer.print("mNextAnim="); writer.println(mNextAnim); 1384 } 1385 if (mContainer != null) { 1386 writer.print(prefix); writer.print("mContainer="); writer.println(mContainer); 1387 } 1388 if (mView != null) { 1389 writer.print(prefix); writer.print("mView="); writer.println(mView); 1390 } 1391 if (mInnerView != null) { 1392 writer.print(prefix); writer.print("mInnerView="); writer.println(mView); 1393 } 1394 if (mAnimatingAway != null) { 1395 writer.print(prefix); writer.print("mAnimatingAway="); writer.println(mAnimatingAway); 1396 writer.print(prefix); writer.print("mStateAfterAnimating="); 1397 writer.println(mStateAfterAnimating); 1398 } 1399 if (mLoaderManager != null) { 1400 writer.print(prefix); writer.println("Loader Manager:"); 1401 mLoaderManager.dump(prefix + " ", fd, writer, args); 1402 } 1403 if (mChildFragmentManager != null) { 1404 writer.print(prefix); writer.println("Child " + mChildFragmentManager + ":"); 1405 mChildFragmentManager.dump(prefix + " ", fd, writer, args); 1406 } 1407 } 1408 1409 Fragment findFragmentByWho(String who) { 1410 if (who.equals(mWho)) { 1411 return this; 1412 } 1413 if (mChildFragmentManager != null) { 1414 return mChildFragmentManager.findFragmentByWho(who); 1415 } 1416 return null; 1417 } 1418 1419 void instantiateChildFragmentManager() { 1420 mChildFragmentManager = new FragmentManagerImpl(); 1421 mChildFragmentManager.attachActivity(mActivity, new FragmentContainer() { 1422 @Override 1423 public View findViewById(int id) { 1424 if (mView == null) { 1425 throw new IllegalStateException("Fragment does not have a view"); 1426 } 1427 return mView.findViewById(id); 1428 } 1429 }, this); 1430 } 1431 1432 void performCreate(Bundle savedInstanceState) { 1433 if (mChildFragmentManager != null) { 1434 mChildFragmentManager.noteStateNotSaved(); 1435 } 1436 mCalled = false; 1437 onCreate(savedInstanceState); 1438 if (!mCalled) { 1439 throw new SuperNotCalledException("Fragment " + this 1440 + " did not call through to super.onCreate()"); 1441 } 1442 if (savedInstanceState != null) { 1443 Parcelable p = savedInstanceState.getParcelable( 1444 FragmentActivity.FRAGMENTS_TAG); 1445 if (p != null) { 1446 if (mChildFragmentManager == null) { 1447 instantiateChildFragmentManager(); 1448 } 1449 mChildFragmentManager.restoreAllState(p, null); 1450 mChildFragmentManager.dispatchCreate(); 1451 } 1452 } 1453 } 1454 1455 View performCreateView(LayoutInflater inflater, ViewGroup container, 1456 Bundle savedInstanceState) { 1457 if (mChildFragmentManager != null) { 1458 mChildFragmentManager.noteStateNotSaved(); 1459 } 1460 return onCreateView(inflater, container, savedInstanceState); 1461 } 1462 1463 void performActivityCreated(Bundle savedInstanceState) { 1464 if (mChildFragmentManager != null) { 1465 mChildFragmentManager.noteStateNotSaved(); 1466 } 1467 mCalled = false; 1468 onActivityCreated(savedInstanceState); 1469 if (!mCalled) { 1470 throw new SuperNotCalledException("Fragment " + this 1471 + " did not call through to super.onActivityCreated()"); 1472 } 1473 if (mChildFragmentManager != null) { 1474 mChildFragmentManager.dispatchActivityCreated(); 1475 } 1476 } 1477 1478 void performStart() { 1479 if (mChildFragmentManager != null) { 1480 mChildFragmentManager.noteStateNotSaved(); 1481 mChildFragmentManager.execPendingActions(); 1482 } 1483 mCalled = false; 1484 onStart(); 1485 if (!mCalled) { 1486 throw new SuperNotCalledException("Fragment " + this 1487 + " did not call through to super.onStart()"); 1488 } 1489 if (mChildFragmentManager != null) { 1490 mChildFragmentManager.dispatchStart(); 1491 } 1492 if (mLoaderManager != null) { 1493 mLoaderManager.doReportStart(); 1494 } 1495 } 1496 1497 void performResume() { 1498 if (mChildFragmentManager != null) { 1499 mChildFragmentManager.noteStateNotSaved(); 1500 mChildFragmentManager.execPendingActions(); 1501 } 1502 mCalled = false; 1503 onResume(); 1504 if (!mCalled) { 1505 throw new SuperNotCalledException("Fragment " + this 1506 + " did not call through to super.onResume()"); 1507 } 1508 if (mChildFragmentManager != null) { 1509 mChildFragmentManager.dispatchResume(); 1510 mChildFragmentManager.execPendingActions(); 1511 } 1512 } 1513 1514 void performConfigurationChanged(Configuration newConfig) { 1515 onConfigurationChanged(newConfig); 1516 if (mChildFragmentManager != null) { 1517 mChildFragmentManager.dispatchConfigurationChanged(newConfig); 1518 } 1519 } 1520 1521 void performLowMemory() { 1522 onLowMemory(); 1523 if (mChildFragmentManager != null) { 1524 mChildFragmentManager.dispatchLowMemory(); 1525 } 1526 } 1527 1528 /* 1529 void performTrimMemory(int level) { 1530 onTrimMemory(level); 1531 if (mChildFragmentManager != null) { 1532 mChildFragmentManager.dispatchTrimMemory(level); 1533 } 1534 } 1535 */ 1536 1537 boolean performCreateOptionsMenu(Menu menu, MenuInflater inflater) { 1538 boolean show = false; 1539 if (!mHidden) { 1540 if (mHasMenu && mMenuVisible) { 1541 show = true; 1542 onCreateOptionsMenu(menu, inflater); 1543 } 1544 if (mChildFragmentManager != null) { 1545 show |= mChildFragmentManager.dispatchCreateOptionsMenu(menu, inflater); 1546 } 1547 } 1548 return show; 1549 } 1550 1551 boolean performPrepareOptionsMenu(Menu menu) { 1552 boolean show = false; 1553 if (!mHidden) { 1554 if (mHasMenu && mMenuVisible) { 1555 show = true; 1556 onPrepareOptionsMenu(menu); 1557 } 1558 if (mChildFragmentManager != null) { 1559 show |= mChildFragmentManager.dispatchPrepareOptionsMenu(menu); 1560 } 1561 } 1562 return show; 1563 } 1564 1565 boolean performOptionsItemSelected(MenuItem item) { 1566 if (!mHidden) { 1567 if (mHasMenu && mMenuVisible) { 1568 if (onOptionsItemSelected(item)) { 1569 return true; 1570 } 1571 } 1572 if (mChildFragmentManager != null) { 1573 if (mChildFragmentManager.dispatchOptionsItemSelected(item)) { 1574 return true; 1575 } 1576 } 1577 } 1578 return false; 1579 } 1580 1581 boolean performContextItemSelected(MenuItem item) { 1582 if (!mHidden) { 1583 if (onContextItemSelected(item)) { 1584 return true; 1585 } 1586 if (mChildFragmentManager != null) { 1587 if (mChildFragmentManager.dispatchContextItemSelected(item)) { 1588 return true; 1589 } 1590 } 1591 } 1592 return false; 1593 } 1594 1595 void performOptionsMenuClosed(Menu menu) { 1596 if (!mHidden) { 1597 if (mHasMenu && mMenuVisible) { 1598 onOptionsMenuClosed(menu); 1599 } 1600 if (mChildFragmentManager != null) { 1601 mChildFragmentManager.dispatchOptionsMenuClosed(menu); 1602 } 1603 } 1604 } 1605 1606 void performSaveInstanceState(Bundle outState) { 1607 onSaveInstanceState(outState); 1608 if (mChildFragmentManager != null) { 1609 Parcelable p = mChildFragmentManager.saveAllState(); 1610 if (p != null) { 1611 outState.putParcelable(FragmentActivity.FRAGMENTS_TAG, p); 1612 } 1613 } 1614 } 1615 1616 void performPause() { 1617 if (mChildFragmentManager != null) { 1618 mChildFragmentManager.dispatchPause(); 1619 } 1620 mCalled = false; 1621 onPause(); 1622 if (!mCalled) { 1623 throw new SuperNotCalledException("Fragment " + this 1624 + " did not call through to super.onPause()"); 1625 } 1626 } 1627 1628 void performStop() { 1629 if (mChildFragmentManager != null) { 1630 mChildFragmentManager.dispatchStop(); 1631 } 1632 mCalled = false; 1633 onStop(); 1634 if (!mCalled) { 1635 throw new SuperNotCalledException("Fragment " + this 1636 + " did not call through to super.onStop()"); 1637 } 1638 } 1639 1640 void performReallyStop() { 1641 if (mChildFragmentManager != null) { 1642 mChildFragmentManager.dispatchReallyStop(); 1643 } 1644 if (mLoadersStarted) { 1645 mLoadersStarted = false; 1646 if (!mCheckedForLoaderManager) { 1647 mCheckedForLoaderManager = true; 1648 mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false); 1649 } 1650 if (mLoaderManager != null) { 1651 if (!mActivity.mRetaining) { 1652 mLoaderManager.doStop(); 1653 } else { 1654 mLoaderManager.doRetain(); 1655 } 1656 } 1657 } 1658 } 1659 1660 void performDestroyView() { 1661 if (mChildFragmentManager != null) { 1662 mChildFragmentManager.dispatchDestroyView(); 1663 } 1664 mCalled = false; 1665 onDestroyView(); 1666 if (!mCalled) { 1667 throw new SuperNotCalledException("Fragment " + this 1668 + " did not call through to super.onDestroyView()"); 1669 } 1670 if (mLoaderManager != null) { 1671 mLoaderManager.doReportNextStart(); 1672 } 1673 } 1674 1675 void performDestroy() { 1676 if (mChildFragmentManager != null) { 1677 mChildFragmentManager.dispatchDestroy(); 1678 } 1679 mCalled = false; 1680 onDestroy(); 1681 if (!mCalled) { 1682 throw new SuperNotCalledException("Fragment " + this 1683 + " did not call through to super.onDestroy()"); 1684 } 1685 } 1686} 1687