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