Fragment.java revision a4dd8065e66394cf00e9fcdea4490c12ea917b0d
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 static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; 20 21import android.app.Activity; 22import android.content.ComponentCallbacks; 23import android.content.Context; 24import android.content.Intent; 25import android.content.IntentSender; 26import android.content.res.Configuration; 27import android.content.res.Resources; 28import android.os.Bundle; 29import android.os.Looper; 30import android.os.Parcel; 31import android.os.Parcelable; 32import android.support.annotation.CallSuper; 33import android.support.annotation.NonNull; 34import android.support.annotation.Nullable; 35import android.support.annotation.RestrictTo; 36import android.support.annotation.StringRes; 37import android.support.v4.util.DebugUtils; 38import android.support.v4.util.SimpleArrayMap; 39import android.support.v4.view.LayoutInflaterCompat; 40import android.util.AttributeSet; 41import android.util.Log; 42import android.util.SparseArray; 43import android.view.ContextMenu; 44import android.view.ContextMenu.ContextMenuInfo; 45import android.view.LayoutInflater; 46import android.view.Menu; 47import android.view.MenuInflater; 48import android.view.MenuItem; 49import android.view.View; 50import android.view.View.OnCreateContextMenuListener; 51import android.view.ViewGroup; 52import android.view.animation.Animation; 53import android.widget.AdapterView; 54 55import java.io.FileDescriptor; 56import java.io.PrintWriter; 57 58final class FragmentState implements Parcelable { 59 final String mClassName; 60 final int mIndex; 61 final boolean mFromLayout; 62 final int mFragmentId; 63 final int mContainerId; 64 final String mTag; 65 final boolean mRetainInstance; 66 final boolean mDetached; 67 final Bundle mArguments; 68 final boolean mHidden; 69 70 Bundle mSavedFragmentState; 71 72 Fragment mInstance; 73 74 public FragmentState(Fragment frag) { 75 mClassName = frag.getClass().getName(); 76 mIndex = frag.mIndex; 77 mFromLayout = frag.mFromLayout; 78 mFragmentId = frag.mFragmentId; 79 mContainerId = frag.mContainerId; 80 mTag = frag.mTag; 81 mRetainInstance = frag.mRetainInstance; 82 mDetached = frag.mDetached; 83 mArguments = frag.mArguments; 84 mHidden = frag.mHidden; 85 } 86 87 public FragmentState(Parcel in) { 88 mClassName = in.readString(); 89 mIndex = in.readInt(); 90 mFromLayout = in.readInt() != 0; 91 mFragmentId = in.readInt(); 92 mContainerId = in.readInt(); 93 mTag = in.readString(); 94 mRetainInstance = in.readInt() != 0; 95 mDetached = in.readInt() != 0; 96 mArguments = in.readBundle(); 97 mHidden = in.readInt() != 0; 98 mSavedFragmentState = in.readBundle(); 99 } 100 101 public Fragment instantiate(FragmentHostCallback host, Fragment parent, 102 FragmentManagerNonConfig childNonConfig) { 103 if (mInstance == null) { 104 final Context context = host.getContext(); 105 if (mArguments != null) { 106 mArguments.setClassLoader(context.getClassLoader()); 107 } 108 109 mInstance = Fragment.instantiate(context, mClassName, mArguments); 110 111 if (mSavedFragmentState != null) { 112 mSavedFragmentState.setClassLoader(context.getClassLoader()); 113 mInstance.mSavedFragmentState = mSavedFragmentState; 114 } 115 mInstance.setIndex(mIndex, parent); 116 mInstance.mFromLayout = mFromLayout; 117 mInstance.mRestored = true; 118 mInstance.mFragmentId = mFragmentId; 119 mInstance.mContainerId = mContainerId; 120 mInstance.mTag = mTag; 121 mInstance.mRetainInstance = mRetainInstance; 122 mInstance.mDetached = mDetached; 123 mInstance.mHidden = mHidden; 124 mInstance.mFragmentManager = host.mFragmentManager; 125 126 if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG, 127 "Instantiated fragment " + mInstance); 128 } 129 mInstance.mChildNonConfig = childNonConfig; 130 return mInstance; 131 } 132 133 @Override 134 public int describeContents() { 135 return 0; 136 } 137 138 @Override 139 public void writeToParcel(Parcel dest, int flags) { 140 dest.writeString(mClassName); 141 dest.writeInt(mIndex); 142 dest.writeInt(mFromLayout ? 1 : 0); 143 dest.writeInt(mFragmentId); 144 dest.writeInt(mContainerId); 145 dest.writeString(mTag); 146 dest.writeInt(mRetainInstance ? 1 : 0); 147 dest.writeInt(mDetached ? 1 : 0); 148 dest.writeBundle(mArguments); 149 dest.writeInt(mHidden? 1 : 0); 150 dest.writeBundle(mSavedFragmentState); 151 } 152 153 public static final Parcelable.Creator<FragmentState> CREATOR 154 = new Parcelable.Creator<FragmentState>() { 155 @Override 156 public FragmentState createFromParcel(Parcel in) { 157 return new FragmentState(in); 158 } 159 160 @Override 161 public FragmentState[] newArray(int size) { 162 return new FragmentState[size]; 163 } 164 }; 165} 166 167/** 168 * Static library support version of the framework's {@link android.app.Fragment}. 169 * Used to write apps that run on platforms prior to Android 3.0. When running 170 * on Android 3.0 or above, this implementation is still used; it does not try 171 * to switch to the framework's implementation. See the framework {@link android.app.Fragment} 172 * documentation for a class overview. 173 * 174 * <p>The main differences when using this support version instead of the framework version are: 175 * <ul> 176 * <li>Your activity must extend {@link FragmentActivity} 177 * <li>You must call {@link FragmentActivity#getSupportFragmentManager} to get the 178 * {@link FragmentManager} 179 * </ul> 180 * 181 */ 182public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener { 183 private static final SimpleArrayMap<String, Class<?>> sClassMap = 184 new SimpleArrayMap<String, Class<?>>(); 185 186 static final Object USE_DEFAULT_TRANSITION = new Object(); 187 188 static final int INITIALIZING = 0; // Not yet created. 189 static final int CREATED = 1; // Created. 190 static final int ACTIVITY_CREATED = 2; // The activity has finished its creation. 191 static final int STOPPED = 3; // Fully created, not started. 192 static final int STARTED = 4; // Created and started, not resumed. 193 static final int RESUMED = 5; // Created started and resumed. 194 195 int mState = INITIALIZING; 196 197 // When instantiated from saved state, this is the saved state. 198 Bundle mSavedFragmentState; 199 SparseArray<Parcelable> mSavedViewState; 200 201 // Index into active fragment array. 202 int mIndex = -1; 203 204 // Internal unique name for this fragment; 205 String mWho; 206 207 // Construction arguments; 208 Bundle mArguments; 209 210 // Target fragment. 211 Fragment mTarget; 212 213 // For use when retaining a fragment: this is the index of the last mTarget. 214 int mTargetIndex = -1; 215 216 // Target request code. 217 int mTargetRequestCode; 218 219 // True if the fragment is in the list of added fragments. 220 boolean mAdded; 221 222 // If set this fragment is being removed from its activity. 223 boolean mRemoving; 224 225 // Set to true if this fragment was instantiated from a layout file. 226 boolean mFromLayout; 227 228 // Set to true when the view has actually been inflated in its layout. 229 boolean mInLayout; 230 231 // True if this fragment has been restored from previously saved state. 232 boolean mRestored; 233 234 // True if performCreateView has been called and a matching call to performDestroyView 235 // has not yet happened. 236 boolean mPerformedCreateView; 237 238 // Number of active back stack entries this fragment is in. 239 int mBackStackNesting; 240 241 // The fragment manager we are associated with. Set as soon as the 242 // fragment is used in a transaction; cleared after it has been removed 243 // from all transactions. 244 FragmentManagerImpl mFragmentManager; 245 246 // Host this fragment is attached to. 247 FragmentHostCallback mHost; 248 249 // Private fragment manager for child fragments inside of this one. 250 FragmentManagerImpl mChildFragmentManager; 251 252 // For use when restoring fragment state and descendant fragments are retained. 253 // This state is set by FragmentState.instantiate and cleared in onCreate. 254 FragmentManagerNonConfig mChildNonConfig; 255 256 // If this Fragment is contained in another Fragment, this is that container. 257 Fragment mParentFragment; 258 259 // The optional identifier for this fragment -- either the container ID if it 260 // was dynamically added to the view hierarchy, or the ID supplied in 261 // layout. 262 int mFragmentId; 263 264 // When a fragment is being dynamically added to the view hierarchy, this 265 // is the identifier of the parent container it is being added to. 266 int mContainerId; 267 268 // The optional named tag for this fragment -- usually used to find 269 // fragments that are not part of the layout. 270 String mTag; 271 272 // Set to true when the app has requested that this fragment be hidden 273 // from the user. 274 boolean mHidden; 275 276 // Set to true when the app has requested that this fragment be deactivated. 277 boolean mDetached; 278 279 // If set this fragment would like its instance retained across 280 // configuration changes. 281 boolean mRetainInstance; 282 283 // If set this fragment is being retained across the current config change. 284 boolean mRetaining; 285 286 // If set this fragment has menu items to contribute. 287 boolean mHasMenu; 288 289 // Set to true to allow the fragment's menu to be shown. 290 boolean mMenuVisible = true; 291 292 // Used to verify that subclasses call through to super class. 293 boolean mCalled; 294 295 // The parent container of the fragment after dynamically added to UI. 296 ViewGroup mContainer; 297 298 // The View generated for this fragment. 299 View mView; 300 301 // The real inner view that will save/restore state. 302 View mInnerView; 303 304 // Whether this fragment should defer starting until after other fragments 305 // have been started and their loaders are finished. 306 boolean mDeferStart; 307 308 // Hint provided by the app that this fragment is currently visible to the user. 309 boolean mUserVisibleHint = true; 310 311 LoaderManagerImpl mLoaderManager; 312 boolean mLoadersStarted; 313 boolean mCheckedForLoaderManager; 314 315 // The animation and transition information for the fragment. This will be null 316 // unless the elements are explicitly accessed and should remain null for Fragments 317 // without Views. 318 AnimationInfo mAnimationInfo; 319 320 // True if the View was added, and its animation has yet to be run. This could 321 // also indicate that the fragment view hasn't been made visible, even if there is no 322 // animation for this fragment. 323 boolean mIsNewlyAdded; 324 325 // True if mHidden has been changed and the animation should be scheduled. 326 boolean mHiddenChanged; 327 328 // The alpha of the view when the view was added and then postponed. If the value is less 329 // than zero, this means that the view's add was canceled and should not participate in 330 // removal animations. 331 float mPostponedAlpha; 332 333 /** 334 * State information that has been retrieved from a fragment instance 335 * through {@link FragmentManager#saveFragmentInstanceState(Fragment) 336 * FragmentManager.saveFragmentInstanceState}. 337 */ 338 public static class SavedState implements Parcelable { 339 final Bundle mState; 340 341 SavedState(Bundle state) { 342 mState = state; 343 } 344 345 SavedState(Parcel in, ClassLoader loader) { 346 mState = in.readBundle(); 347 if (loader != null && mState != null) { 348 mState.setClassLoader(loader); 349 } 350 } 351 352 @Override 353 public int describeContents() { 354 return 0; 355 } 356 357 @Override 358 public void writeToParcel(Parcel dest, int flags) { 359 dest.writeBundle(mState); 360 } 361 362 public static final Parcelable.Creator<SavedState> CREATOR 363 = new Parcelable.Creator<SavedState>() { 364 @Override 365 public SavedState createFromParcel(Parcel in) { 366 return new SavedState(in, null); 367 } 368 369 @Override 370 public SavedState[] newArray(int size) { 371 return new SavedState[size]; 372 } 373 }; 374 } 375 376 /** 377 * Thrown by {@link Fragment#instantiate(Context, String, Bundle)} when 378 * there is an instantiation failure. 379 */ 380 static public class InstantiationException extends RuntimeException { 381 public InstantiationException(String msg, Exception cause) { 382 super(msg, cause); 383 } 384 } 385 386 /** 387 * Default constructor. <strong>Every</strong> fragment must have an 388 * empty constructor, so it can be instantiated when restoring its 389 * activity's state. It is strongly recommended that subclasses do not 390 * have other constructors with parameters, since these constructors 391 * will not be called when the fragment is re-instantiated; instead, 392 * arguments can be supplied by the caller with {@link #setArguments} 393 * and later retrieved by the Fragment with {@link #getArguments}. 394 * 395 * <p>Applications should generally not implement a constructor. Prefer 396 * {@link #onAttach(Context)} instead. It is the first place application code can run where 397 * the fragment is ready to be used - the point where the fragment is actually associated with 398 * its context. Some applications may also want to implement {@link #onInflate} to retrieve 399 * attributes from a layout resource, although note this happens when the fragment is attached. 400 */ 401 public Fragment() { 402 } 403 404 /** 405 * Like {@link #instantiate(Context, String, Bundle)} but with a null 406 * argument Bundle. 407 */ 408 public static Fragment instantiate(Context context, String fname) { 409 return instantiate(context, fname, null); 410 } 411 412 /** 413 * Create a new instance of a Fragment with the given class name. This is 414 * the same as calling its empty constructor. 415 * 416 * @param context The calling context being used to instantiate the fragment. 417 * This is currently just used to get its ClassLoader. 418 * @param fname The class name of the fragment to instantiate. 419 * @param args Bundle of arguments to supply to the fragment, which it 420 * can retrieve with {@link #getArguments()}. May be null. 421 * @return Returns a new fragment instance. 422 * @throws InstantiationException If there is a failure in instantiating 423 * the given fragment class. This is a runtime exception; it is not 424 * normally expected to happen. 425 */ 426 public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) { 427 try { 428 Class<?> clazz = sClassMap.get(fname); 429 if (clazz == null) { 430 // Class not found in the cache, see if it's real, and try to add it 431 clazz = context.getClassLoader().loadClass(fname); 432 sClassMap.put(fname, clazz); 433 } 434 Fragment f = (Fragment)clazz.newInstance(); 435 if (args != null) { 436 args.setClassLoader(f.getClass().getClassLoader()); 437 f.setArguments(args); 438 } 439 return f; 440 } catch (ClassNotFoundException e) { 441 throw new InstantiationException("Unable to instantiate fragment " + fname 442 + ": make sure class name exists, is public, and has an" 443 + " empty constructor that is public", e); 444 } catch (java.lang.InstantiationException e) { 445 throw new InstantiationException("Unable to instantiate fragment " + fname 446 + ": make sure class name exists, is public, and has an" 447 + " empty constructor that is public", e); 448 } catch (IllegalAccessException e) { 449 throw new InstantiationException("Unable to instantiate fragment " + fname 450 + ": make sure class name exists, is public, and has an" 451 + " empty constructor that is public", e); 452 } 453 } 454 455 /** 456 * Determine if the given fragment name is a support library fragment class. 457 * 458 * @param context Context used to determine the correct ClassLoader to use 459 * @param fname Class name of the fragment to test 460 * @return true if <code>fname</code> is <code>android.support.v4.app.Fragment</code> 461 * or a subclass, false otherwise. 462 */ 463 static boolean isSupportFragmentClass(Context context, String fname) { 464 try { 465 Class<?> clazz = sClassMap.get(fname); 466 if (clazz == null) { 467 // Class not found in the cache, see if it's real, and try to add it 468 clazz = context.getClassLoader().loadClass(fname); 469 sClassMap.put(fname, clazz); 470 } 471 return Fragment.class.isAssignableFrom(clazz); 472 } catch (ClassNotFoundException e) { 473 return false; 474 } 475 } 476 477 final void restoreViewState(Bundle savedInstanceState) { 478 if (mSavedViewState != null) { 479 mInnerView.restoreHierarchyState(mSavedViewState); 480 mSavedViewState = null; 481 } 482 mCalled = false; 483 onViewStateRestored(savedInstanceState); 484 if (!mCalled) { 485 throw new SuperNotCalledException("Fragment " + this 486 + " did not call through to super.onViewStateRestored()"); 487 } 488 } 489 490 final void setIndex(int index, Fragment parent) { 491 mIndex = index; 492 if (parent != null) { 493 mWho = parent.mWho + ":" + mIndex; 494 } else { 495 mWho = "android:fragment:" + mIndex; 496 } 497 } 498 499 final boolean isInBackStack() { 500 return mBackStackNesting > 0; 501 } 502 503 /** 504 * Subclasses can not override equals(). 505 */ 506 @Override final public boolean equals(Object o) { 507 return super.equals(o); 508 } 509 510 /** 511 * Subclasses can not override hashCode(). 512 */ 513 @Override final public int hashCode() { 514 return super.hashCode(); 515 } 516 517 @Override 518 public String toString() { 519 StringBuilder sb = new StringBuilder(128); 520 DebugUtils.buildShortClassTag(this, sb); 521 if (mIndex >= 0) { 522 sb.append(" #"); 523 sb.append(mIndex); 524 } 525 if (mFragmentId != 0) { 526 sb.append(" id=0x"); 527 sb.append(Integer.toHexString(mFragmentId)); 528 } 529 if (mTag != null) { 530 sb.append(" "); 531 sb.append(mTag); 532 } 533 sb.append('}'); 534 return sb.toString(); 535 } 536 537 /** 538 * Return the identifier this fragment is known by. This is either 539 * the android:id value supplied in a layout or the container view ID 540 * supplied when adding the fragment. 541 */ 542 final public int getId() { 543 return mFragmentId; 544 } 545 546 /** 547 * Get the tag name of the fragment, if specified. 548 */ 549 final public String getTag() { 550 return mTag; 551 } 552 553 /** 554 * Supply the construction arguments for this fragment. This can only 555 * be called before the fragment has been attached to its activity; that 556 * is, you should call it immediately after constructing the fragment. The 557 * arguments supplied here will be retained across fragment destroy and 558 * creation. 559 */ 560 public void setArguments(Bundle args) { 561 if (mIndex >= 0) { 562 throw new IllegalStateException("Fragment already active"); 563 } 564 mArguments = args; 565 } 566 567 /** 568 * Return the arguments supplied when the fragment was instantiated, 569 * if any. 570 */ 571 final public Bundle getArguments() { 572 return mArguments; 573 } 574 575 /** 576 * Set the initial saved state that this Fragment should restore itself 577 * from when first being constructed, as returned by 578 * {@link FragmentManager#saveFragmentInstanceState(Fragment) 579 * FragmentManager.saveFragmentInstanceState}. 580 * 581 * @param state The state the fragment should be restored from. 582 */ 583 public void setInitialSavedState(SavedState state) { 584 if (mIndex >= 0) { 585 throw new IllegalStateException("Fragment already active"); 586 } 587 mSavedFragmentState = state != null && state.mState != null 588 ? state.mState : null; 589 } 590 591 /** 592 * Optional target for this fragment. This may be used, for example, 593 * if this fragment is being started by another, and when done wants to 594 * give a result back to the first. The target set here is retained 595 * across instances via {@link FragmentManager#putFragment 596 * FragmentManager.putFragment()}. 597 * 598 * @param fragment The fragment that is the target of this one. 599 * @param requestCode Optional request code, for convenience if you 600 * are going to call back with {@link #onActivityResult(int, int, Intent)}. 601 */ 602 public void setTargetFragment(Fragment fragment, int requestCode) { 603 mTarget = fragment; 604 mTargetRequestCode = requestCode; 605 } 606 607 /** 608 * Return the target fragment set by {@link #setTargetFragment}. 609 */ 610 final public Fragment getTargetFragment() { 611 return mTarget; 612 } 613 614 /** 615 * Return the target request code set by {@link #setTargetFragment}. 616 */ 617 final public int getTargetRequestCode() { 618 return mTargetRequestCode; 619 } 620 621 /** 622 * Return the {@link Context} this fragment is currently associated with. 623 */ 624 public Context getContext() { 625 return mHost == null ? null : mHost.getContext(); 626 } 627 628 /** 629 * Return the {@link FragmentActivity} this fragment is currently associated with. 630 * May return {@code null} if the fragment is associated with a {@link Context} 631 * instead. 632 */ 633 final public FragmentActivity getActivity() { 634 return mHost == null ? null : (FragmentActivity) mHost.getActivity(); 635 } 636 637 /** 638 * Return the host object of this fragment. May return {@code null} if the fragment 639 * isn't currently being hosted. 640 */ 641 final public Object getHost() { 642 return mHost == null ? null : mHost.onGetHost(); 643 } 644 645 /** 646 * Return <code>getActivity().getResources()</code>. 647 */ 648 final public Resources getResources() { 649 if (mHost == null) { 650 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 651 } 652 return mHost.getContext().getResources(); 653 } 654 655 /** 656 * Return a localized, styled CharSequence from the application's package's 657 * default string table. 658 * 659 * @param resId Resource id for the CharSequence text 660 */ 661 public final CharSequence getText(@StringRes int resId) { 662 return getResources().getText(resId); 663 } 664 665 /** 666 * Return a localized string from the application's package's 667 * default string table. 668 * 669 * @param resId Resource id for the string 670 */ 671 public final String getString(@StringRes int resId) { 672 return getResources().getString(resId); 673 } 674 675 /** 676 * Return a localized formatted string from the application's package's 677 * default string table, substituting the format arguments as defined in 678 * {@link java.util.Formatter} and {@link java.lang.String#format}. 679 * 680 * @param resId Resource id for the format string 681 * @param formatArgs The format arguments that will be used for substitution. 682 */ 683 684 public final String getString(@StringRes int resId, Object... formatArgs) { 685 return getResources().getString(resId, formatArgs); 686 } 687 688 /** 689 * Return the FragmentManager for interacting with fragments associated 690 * with this fragment's activity. Note that this will be non-null slightly 691 * before {@link #getActivity()}, during the time from when the fragment is 692 * placed in a {@link FragmentTransaction} until it is committed and 693 * attached to its activity. 694 * 695 * <p>If this Fragment is a child of another Fragment, the FragmentManager 696 * returned here will be the parent's {@link #getChildFragmentManager()}. 697 */ 698 final public FragmentManager getFragmentManager() { 699 return mFragmentManager; 700 } 701 702 /** 703 * Return a private FragmentManager for placing and managing Fragments 704 * inside of this Fragment. 705 */ 706 final public FragmentManager getChildFragmentManager() { 707 if (mChildFragmentManager == null) { 708 instantiateChildFragmentManager(); 709 if (mState >= RESUMED) { 710 mChildFragmentManager.dispatchResume(); 711 } else if (mState >= STARTED) { 712 mChildFragmentManager.dispatchStart(); 713 } else if (mState >= ACTIVITY_CREATED) { 714 mChildFragmentManager.dispatchActivityCreated(); 715 } else if (mState >= CREATED) { 716 mChildFragmentManager.dispatchCreate(); 717 } 718 } 719 return mChildFragmentManager; 720 } 721 722 /** 723 * Return this fragment's child FragmentManager one has been previously created, 724 * otherwise null. 725 */ 726 FragmentManager peekChildFragmentManager() { 727 return mChildFragmentManager; 728 } 729 730 /** 731 * Returns the parent Fragment containing this Fragment. If this Fragment 732 * is attached directly to an Activity, returns null. 733 */ 734 final public Fragment getParentFragment() { 735 return mParentFragment; 736 } 737 738 /** 739 * Return true if the fragment is currently added to its activity. 740 */ 741 final public boolean isAdded() { 742 return mHost != null && mAdded; 743 } 744 745 /** 746 * Return true if the fragment has been explicitly detached from the UI. 747 * That is, {@link FragmentTransaction#detach(Fragment) 748 * FragmentTransaction.detach(Fragment)} has been used on it. 749 */ 750 final public boolean isDetached() { 751 return mDetached; 752 } 753 754 /** 755 * Return true if this fragment is currently being removed from its 756 * activity. This is <em>not</em> whether its activity is finishing, but 757 * rather whether it is in the process of being removed from its activity. 758 */ 759 final public boolean isRemoving() { 760 return mRemoving; 761 } 762 763 /** 764 * Return true if the layout is included as part of an activity view 765 * hierarchy via the <fragment> tag. This will always be true when 766 * fragments are created through the <fragment> tag, <em>except</em> 767 * in the case where an old fragment is restored from a previous state and 768 * it does not appear in the layout of the current state. 769 */ 770 final public boolean isInLayout() { 771 return mInLayout; 772 } 773 774 /** 775 * Return true if the fragment is in the resumed state. This is true 776 * for the duration of {@link #onResume()} and {@link #onPause()} as well. 777 */ 778 final public boolean isResumed() { 779 return mState >= RESUMED; 780 } 781 782 /** 783 * Return true if the fragment is currently visible to the user. This means 784 * it: (1) has been added, (2) has its view attached to the window, and 785 * (3) is not hidden. 786 */ 787 final public boolean isVisible() { 788 return isAdded() && !isHidden() && mView != null 789 && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE; 790 } 791 792 /** 793 * Return true if the fragment has been hidden. By default fragments 794 * are shown. You can find out about changes to this state with 795 * {@link #onHiddenChanged}. Note that the hidden state is orthogonal 796 * to other states -- that is, to be visible to the user, a fragment 797 * must be both started and not hidden. 798 */ 799 final public boolean isHidden() { 800 return mHidden; 801 } 802 803 /** @hide */ 804 @RestrictTo(LIBRARY_GROUP) 805 final public boolean hasOptionsMenu() { 806 return mHasMenu; 807 } 808 809 /** @hide */ 810 @RestrictTo(LIBRARY_GROUP) 811 final public boolean isMenuVisible() { 812 return mMenuVisible; 813 } 814 815 /** 816 * Called when the hidden state (as returned by {@link #isHidden()} of 817 * the fragment has changed. Fragments start out not hidden; this will 818 * be called whenever the fragment changes state from that. 819 * @param hidden True if the fragment is now hidden, false otherwise. 820 */ 821 public void onHiddenChanged(boolean hidden) { 822 } 823 824 /** 825 * Control whether a fragment instance is retained across Activity 826 * re-creation (such as from a configuration change). This can only 827 * be used with fragments not in the back stack. If set, the fragment 828 * lifecycle will be slightly different when an activity is recreated: 829 * <ul> 830 * <li> {@link #onDestroy()} will not be called (but {@link #onDetach()} still 831 * will be, because the fragment is being detached from its current activity). 832 * <li> {@link #onCreate(Bundle)} will not be called since the fragment 833 * is not being re-created. 834 * <li> {@link #onAttach(Activity)} and {@link #onActivityCreated(Bundle)} <b>will</b> 835 * still be called. 836 * </ul> 837 */ 838 public void setRetainInstance(boolean retain) { 839 mRetainInstance = retain; 840 } 841 842 final public boolean getRetainInstance() { 843 return mRetainInstance; 844 } 845 846 /** 847 * Report that this fragment would like to participate in populating 848 * the options menu by receiving a call to {@link #onCreateOptionsMenu} 849 * and related methods. 850 * 851 * @param hasMenu If true, the fragment has menu items to contribute. 852 */ 853 public void setHasOptionsMenu(boolean hasMenu) { 854 if (mHasMenu != hasMenu) { 855 mHasMenu = hasMenu; 856 if (isAdded() && !isHidden()) { 857 mHost.onSupportInvalidateOptionsMenu(); 858 } 859 } 860 } 861 862 /** 863 * Set a hint for whether this fragment's menu should be visible. This 864 * is useful if you know that a fragment has been placed in your view 865 * hierarchy so that the user can not currently seen it, so any menu items 866 * it has should also not be shown. 867 * 868 * @param menuVisible The default is true, meaning the fragment's menu will 869 * be shown as usual. If false, the user will not see the menu. 870 */ 871 public void setMenuVisibility(boolean menuVisible) { 872 if (mMenuVisible != menuVisible) { 873 mMenuVisible = menuVisible; 874 if (mHasMenu && isAdded() && !isHidden()) { 875 mHost.onSupportInvalidateOptionsMenu(); 876 } 877 } 878 } 879 880 /** 881 * Set a hint to the system about whether this fragment's UI is currently visible 882 * to the user. This hint defaults to true and is persistent across fragment instance 883 * state save and restore. 884 * 885 * <p>An app may set this to false to indicate that the fragment's UI is 886 * scrolled out of visibility or is otherwise not directly visible to the user. 887 * This may be used by the system to prioritize operations such as fragment lifecycle updates 888 * or loader ordering behavior.</p> 889 * 890 * <p><strong>Note:</strong> This method may be called outside of the fragment lifecycle. 891 * and thus has no ordering guarantees with regard to fragment lifecycle method calls.</p> 892 * 893 * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default), 894 * false if it is not. 895 */ 896 public void setUserVisibleHint(boolean isVisibleToUser) { 897 if (!mUserVisibleHint && isVisibleToUser && mState < STARTED 898 && mFragmentManager != null && isAdded()) { 899 mFragmentManager.performPendingDeferredStart(this); 900 } 901 mUserVisibleHint = isVisibleToUser; 902 mDeferStart = mState < STARTED && !isVisibleToUser; 903 } 904 905 /** 906 * @return The current value of the user-visible hint on this fragment. 907 * @see #setUserVisibleHint(boolean) 908 */ 909 public boolean getUserVisibleHint() { 910 return mUserVisibleHint; 911 } 912 913 /** 914 * Return the LoaderManager for this fragment, creating it if needed. 915 */ 916 public LoaderManager getLoaderManager() { 917 if (mLoaderManager != null) { 918 return mLoaderManager; 919 } 920 if (mHost == null) { 921 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 922 } 923 mCheckedForLoaderManager = true; 924 mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, true); 925 return mLoaderManager; 926 } 927 928 /** 929 * Call {@link Activity#startActivity(Intent)} from the fragment's 930 * containing Activity. 931 */ 932 public void startActivity(Intent intent) { 933 startActivity(intent, null); 934 } 935 936 /** 937 * Call {@link Activity#startActivity(Intent, Bundle)} from the fragment's 938 * containing Activity. 939 */ 940 public void startActivity(Intent intent, @Nullable Bundle options) { 941 if (mHost == null) { 942 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 943 } 944 mHost.onStartActivityFromFragment(this /*fragment*/, intent, -1, options); 945 } 946 947 /** 948 * Call {@link Activity#startActivityForResult(Intent, int)} from the fragment's 949 * containing Activity. 950 */ 951 public void startActivityForResult(Intent intent, int requestCode) { 952 startActivityForResult(intent, requestCode, null); 953 } 954 955 /** 956 * Call {@link Activity#startActivityForResult(Intent, int, Bundle)} from the fragment's 957 * containing Activity. 958 */ 959 public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { 960 if (mHost == null) { 961 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 962 } 963 mHost.onStartActivityFromFragment(this /*fragment*/, intent, requestCode, options); 964 } 965 966 /** 967 * Call {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int, 968 * Bundle)} from the fragment's containing Activity. 969 */ 970 public void startIntentSenderForResult(IntentSender intent, int requestCode, 971 @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, 972 Bundle options) throws IntentSender.SendIntentException { 973 if (mHost == null) { 974 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 975 } 976 mHost.onStartIntentSenderFromFragment(this, intent, requestCode, fillInIntent, flagsMask, 977 flagsValues, extraFlags, options); 978 } 979 980 /** 981 * Receive the result from a previous call to 982 * {@link #startActivityForResult(Intent, int)}. This follows the 983 * related Activity API as described there in 984 * {@link Activity#onActivityResult(int, int, Intent)}. 985 * 986 * @param requestCode The integer request code originally supplied to 987 * startActivityForResult(), allowing you to identify who this 988 * result came from. 989 * @param resultCode The integer result code returned by the child activity 990 * through its setResult(). 991 * @param data An Intent, which can return result data to the caller 992 * (various data can be attached to Intent "extras"). 993 */ 994 public void onActivityResult(int requestCode, int resultCode, Intent data) { 995 } 996 997 /** 998 * Requests permissions to be granted to this application. These permissions 999 * must be requested in your manifest, they should not be granted to your app, 1000 * and they should have protection level {@link android.content.pm.PermissionInfo 1001 * #PROTECTION_DANGEROUS dangerous}, regardless whether they are declared by 1002 * the platform or a third-party app. 1003 * <p> 1004 * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL} 1005 * are granted at install time if requested in the manifest. Signature permissions 1006 * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at 1007 * install time if requested in the manifest and the signature of your app matches 1008 * the signature of the app declaring the permissions. 1009 * </p> 1010 * <p> 1011 * If your app does not have the requested permissions the user will be presented 1012 * with UI for accepting them. After the user has accepted or rejected the 1013 * requested permissions you will receive a callback on {@link 1014 * #onRequestPermissionsResult(int, String[], int[])} reporting whether the 1015 * permissions were granted or not. 1016 * </p> 1017 * <p> 1018 * Note that requesting a permission does not guarantee it will be granted and 1019 * your app should be able to run without having this permission. 1020 * </p> 1021 * <p> 1022 * This method may start an activity allowing the user to choose which permissions 1023 * to grant and which to reject. Hence, you should be prepared that your activity 1024 * may be paused and resumed. Further, granting some permissions may require 1025 * a restart of you application. In such a case, the system will recreate the 1026 * activity stack before delivering the result to {@link 1027 * #onRequestPermissionsResult(int, String[], int[])}. 1028 * </p> 1029 * <p> 1030 * When checking whether you have a permission you should use {@link 1031 * android.content.Context#checkSelfPermission(String)}. 1032 * </p> 1033 * <p> 1034 * Calling this API for permissions already granted to your app would show UI 1035 * to the user to decided whether the app can still hold these permissions. This 1036 * can be useful if the way your app uses the data guarded by the permissions 1037 * changes significantly. 1038 * </p> 1039 * <p> 1040 * A sample permissions request looks like this: 1041 * </p> 1042 * <code><pre><p> 1043 * private void showContacts() { 1044 * if (getActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS) 1045 * != PackageManager.PERMISSION_GRANTED) { 1046 * requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 1047 * PERMISSIONS_REQUEST_READ_CONTACTS); 1048 * } else { 1049 * doShowContacts(); 1050 * } 1051 * } 1052 * 1053 * {@literal @}Override 1054 * public void onRequestPermissionsResult(int requestCode, String[] permissions, 1055 * int[] grantResults) { 1056 * if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS 1057 * && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 1058 * doShowContacts(); 1059 * } 1060 * } 1061 * </code></pre></p> 1062 * 1063 * @param permissions The requested permissions. 1064 * @param requestCode Application specific request code to match with a result 1065 * reported to {@link #onRequestPermissionsResult(int, String[], int[])}. 1066 * 1067 * @see #onRequestPermissionsResult(int, String[], int[]) 1068 * @see android.content.Context#checkSelfPermission(String) 1069 */ 1070 public final void requestPermissions(@NonNull String[] permissions, int requestCode) { 1071 if (mHost == null) { 1072 throw new IllegalStateException("Fragment " + this + " not attached to Activity"); 1073 } 1074 mHost.onRequestPermissionsFromFragment(this, permissions, requestCode); 1075 } 1076 1077 /** 1078 * Callback for the result from requesting permissions. This method 1079 * is invoked for every call on {@link #requestPermissions(String[], int)}. 1080 * <p> 1081 * <strong>Note:</strong> It is possible that the permissions request interaction 1082 * with the user is interrupted. In this case you will receive empty permissions 1083 * and results arrays which should be treated as a cancellation. 1084 * </p> 1085 * 1086 * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}. 1087 * @param permissions The requested permissions. Never null. 1088 * @param grantResults The grant results for the corresponding permissions 1089 * which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED} 1090 * or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null. 1091 * 1092 * @see #requestPermissions(String[], int) 1093 */ 1094 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 1095 @NonNull int[] grantResults) { 1096 /* callback - do nothing */ 1097 } 1098 1099 /** 1100 * Gets whether you should show UI with rationale for requesting a permission. 1101 * You should do this only if you do not have the permission and the context in 1102 * which the permission is requested does not clearly communicate to the user 1103 * what would be the benefit from granting this permission. 1104 * <p> 1105 * For example, if you write a camera app, requesting the camera permission 1106 * would be expected by the user and no rationale for why it is requested is 1107 * needed. If however, the app needs location for tagging photos then a non-tech 1108 * savvy user may wonder how location is related to taking photos. In this case 1109 * you may choose to show UI with rationale of requesting this permission. 1110 * </p> 1111 * 1112 * @param permission A permission your app wants to request. 1113 * @return Whether you can show permission rationale UI. 1114 * 1115 * @see Context#checkSelfPermission(String) 1116 * @see #requestPermissions(String[], int) 1117 * @see #onRequestPermissionsResult(int, String[], int[]) 1118 */ 1119 public boolean shouldShowRequestPermissionRationale(@NonNull String permission) { 1120 if (mHost != null) { 1121 return mHost.onShouldShowRequestPermissionRationale(permission); 1122 } 1123 return false; 1124 } 1125 1126 /** 1127 * Hack so that DialogFragment can make its Dialog before creating 1128 * its views, and the view construction can use the dialog's context for 1129 * inflation. Maybe this should become a public API. Note sure. 1130 * @hide 1131 */ 1132 @RestrictTo(LIBRARY_GROUP) 1133 public LayoutInflater getLayoutInflater(Bundle savedInstanceState) { 1134 LayoutInflater result = mHost.onGetLayoutInflater(); 1135 getChildFragmentManager(); // Init if needed; use raw implementation below. 1136 LayoutInflaterCompat.setFactory(result, mChildFragmentManager.getLayoutInflaterFactory()); 1137 return result; 1138 } 1139 1140 /** 1141 * Called when a fragment is being created as part of a view layout 1142 * inflation, typically from setting the content view of an activity. This 1143 * may be called immediately after the fragment is created from a <fragment> 1144 * tag in a layout file. Note this is <em>before</em> the fragment's 1145 * {@link #onAttach(Activity)} has been called; all you should do here is 1146 * parse the attributes and save them away. 1147 * 1148 * <p>This is called every time the fragment is inflated, even if it is 1149 * being inflated into a new instance with saved state. It typically makes 1150 * sense to re-parse the parameters each time, to allow them to change with 1151 * different configurations.</p> 1152 * 1153 * <p>Here is a typical implementation of a fragment that can take parameters 1154 * both through attributes supplied here as well from {@link #getArguments()}:</p> 1155 * 1156 * {@sample frameworks/support/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentArgumentsSupport.java 1157 * fragment} 1158 * 1159 * <p>Note that parsing the XML attributes uses a "styleable" resource. The 1160 * declaration for the styleable used here is:</p> 1161 * 1162 * {@sample frameworks/support/samples/Support4Demos/res/values/attrs.xml fragment_arguments} 1163 * 1164 * <p>The fragment can then be declared within its activity's content layout 1165 * through a tag like this:</p> 1166 * 1167 * {@sample frameworks/support/samples/Support4Demos/res/layout/fragment_arguments_support.xml from_attributes} 1168 * 1169 * <p>This fragment can also be created dynamically from arguments given 1170 * at runtime in the arguments Bundle; here is an example of doing so at 1171 * creation of the containing activity:</p> 1172 * 1173 * {@sample frameworks/support/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentArgumentsSupport.java 1174 * create} 1175 * 1176 * @param context The Activity that is inflating this fragment. 1177 * @param attrs The attributes at the tag where the fragment is 1178 * being created. 1179 * @param savedInstanceState If the fragment is being re-created from 1180 * a previous saved state, this is the state. 1181 */ 1182 @CallSuper 1183 public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) { 1184 mCalled = true; 1185 final Activity hostActivity = mHost == null ? null : mHost.getActivity(); 1186 if (hostActivity != null) { 1187 mCalled = false; 1188 onInflate(hostActivity, attrs, savedInstanceState); 1189 } 1190 } 1191 1192 /** 1193 * Called when a fragment is being created as part of a view layout 1194 * inflation, typically from setting the content view of an activity. 1195 * 1196 * @deprecated See {@link #onInflate(Context, AttributeSet, Bundle)}. 1197 */ 1198 @Deprecated 1199 @CallSuper 1200 public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) { 1201 mCalled = true; 1202 } 1203 1204 /** 1205 * Called when a fragment is attached as a child of this fragment. 1206 * 1207 * <p>This is called after the attached fragment's <code>onAttach</code> and before 1208 * the attached fragment's <code>onCreate</code> if the fragment has not yet had a previous 1209 * call to <code>onCreate</code>.</p> 1210 * 1211 * @param childFragment child fragment being attached 1212 */ 1213 public void onAttachFragment(Fragment childFragment) { 1214 } 1215 1216 /** 1217 * Called when a fragment is first attached to its context. 1218 * {@link #onCreate(Bundle)} will be called after this. 1219 */ 1220 @CallSuper 1221 public void onAttach(Context context) { 1222 mCalled = true; 1223 final Activity hostActivity = mHost == null ? null : mHost.getActivity(); 1224 if (hostActivity != null) { 1225 mCalled = false; 1226 onAttach(hostActivity); 1227 } 1228 } 1229 1230 /** 1231 * Called when a fragment is first attached to its activity. 1232 * {@link #onCreate(Bundle)} will be called after this. 1233 * 1234 * @deprecated See {@link #onAttach(Context)}. 1235 */ 1236 @Deprecated 1237 @CallSuper 1238 public void onAttach(Activity activity) { 1239 mCalled = true; 1240 } 1241 1242 /** 1243 * Called when a fragment loads an animation. 1244 */ 1245 public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { 1246 return null; 1247 } 1248 1249 /** 1250 * Called to do initial creation of a fragment. This is called after 1251 * {@link #onAttach(Activity)} and before 1252 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. 1253 * 1254 * <p>Note that this can be called while the fragment's activity is 1255 * still in the process of being created. As such, you can not rely 1256 * on things like the activity's content view hierarchy being initialized 1257 * at this point. If you want to do work once the activity itself is 1258 * created, see {@link #onActivityCreated(Bundle)}. 1259 * 1260 * <p>Any restored child fragments will be created before the base 1261 * <code>Fragment.onCreate</code> method returns.</p> 1262 * 1263 * @param savedInstanceState If the fragment is being re-created from 1264 * a previous saved state, this is the state. 1265 */ 1266 @CallSuper 1267 public void onCreate(@Nullable Bundle savedInstanceState) { 1268 mCalled = true; 1269 restoreChildFragmentState(savedInstanceState); 1270 if (mChildFragmentManager != null 1271 && !mChildFragmentManager.isStateAtLeast(Fragment.CREATED)) { 1272 mChildFragmentManager.dispatchCreate(); 1273 } 1274 } 1275 1276 /** 1277 * Restore the state of the child FragmentManager. Called by either 1278 * {@link #onCreate(Bundle)} for non-retained instance fragments or by 1279 * {@link FragmentManagerImpl#moveToState(Fragment, int, int, int, boolean)} 1280 * for retained instance fragments. 1281 * 1282 * <p><strong>Postcondition:</strong> if there were child fragments to restore, 1283 * the child FragmentManager will be instantiated and brought to the {@link #CREATED} state. 1284 * </p> 1285 * 1286 * @param savedInstanceState the savedInstanceState potentially containing fragment info 1287 */ 1288 void restoreChildFragmentState(@Nullable Bundle savedInstanceState) { 1289 if (savedInstanceState != null) { 1290 Parcelable p = savedInstanceState.getParcelable( 1291 FragmentActivity.FRAGMENTS_TAG); 1292 if (p != null) { 1293 if (mChildFragmentManager == null) { 1294 instantiateChildFragmentManager(); 1295 } 1296 mChildFragmentManager.restoreAllState(p, mChildNonConfig); 1297 mChildNonConfig = null; 1298 mChildFragmentManager.dispatchCreate(); 1299 } 1300 } 1301 } 1302 1303 /** 1304 * Called to have the fragment instantiate its user interface view. 1305 * This is optional, and non-graphical fragments can return null (which 1306 * is the default implementation). This will be called between 1307 * {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}. 1308 * 1309 * <p>If you return a View from here, you will later be called in 1310 * {@link #onDestroyView} when the view is being released. 1311 * 1312 * @param inflater The LayoutInflater object that can be used to inflate 1313 * any views in the fragment, 1314 * @param container If non-null, this is the parent view that the fragment's 1315 * UI should be attached to. The fragment should not add the view itself, 1316 * but this can be used to generate the LayoutParams of the view. 1317 * @param savedInstanceState If non-null, this fragment is being re-constructed 1318 * from a previous saved state as given here. 1319 * 1320 * @return Return the View for the fragment's UI, or null. 1321 */ 1322 @Nullable 1323 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 1324 @Nullable Bundle savedInstanceState) { 1325 return null; 1326 } 1327 1328 /** 1329 * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} 1330 * has returned, but before any saved state has been restored in to the view. 1331 * This gives subclasses a chance to initialize themselves once 1332 * they know their view hierarchy has been completely created. The fragment's 1333 * view hierarchy is not however attached to its parent at this point. 1334 * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. 1335 * @param savedInstanceState If non-null, this fragment is being re-constructed 1336 * from a previous saved state as given here. 1337 */ 1338 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 1339 } 1340 1341 /** 1342 * Get the root view for the fragment's layout (the one returned by {@link #onCreateView}), 1343 * if provided. 1344 * 1345 * @return The fragment's root view, or null if it has no layout. 1346 */ 1347 @Nullable 1348 public View getView() { 1349 return mView; 1350 } 1351 1352 /** 1353 * Called when the fragment's activity has been created and this 1354 * fragment's view hierarchy instantiated. It can be used to do final 1355 * initialization once these pieces are in place, such as retrieving 1356 * views or restoring state. It is also useful for fragments that use 1357 * {@link #setRetainInstance(boolean)} to retain their instance, 1358 * as this callback tells the fragment when it is fully associated with 1359 * the new activity instance. This is called after {@link #onCreateView} 1360 * and before {@link #onViewStateRestored(Bundle)}. 1361 * 1362 * @param savedInstanceState If the fragment is being re-created from 1363 * a previous saved state, this is the state. 1364 */ 1365 @CallSuper 1366 public void onActivityCreated(@Nullable Bundle savedInstanceState) { 1367 mCalled = true; 1368 } 1369 1370 /** 1371 * Called when all saved state has been restored into the view hierarchy 1372 * of the fragment. This can be used to do initialization based on saved 1373 * state that you are letting the view hierarchy track itself, such as 1374 * whether check box widgets are currently checked. This is called 1375 * after {@link #onActivityCreated(Bundle)} and before 1376 * {@link #onStart()}. 1377 * 1378 * @param savedInstanceState If the fragment is being re-created from 1379 * a previous saved state, this is the state. 1380 */ 1381 @CallSuper 1382 public void onViewStateRestored(@Nullable Bundle savedInstanceState) { 1383 mCalled = true; 1384 } 1385 1386 /** 1387 * Called when the Fragment is visible to the user. This is generally 1388 * tied to {@link Activity#onStart() Activity.onStart} of the containing 1389 * Activity's lifecycle. 1390 */ 1391 @CallSuper 1392 public void onStart() { 1393 mCalled = true; 1394 1395 if (!mLoadersStarted) { 1396 mLoadersStarted = true; 1397 if (!mCheckedForLoaderManager) { 1398 mCheckedForLoaderManager = true; 1399 mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false); 1400 } 1401 if (mLoaderManager != null) { 1402 mLoaderManager.doStart(); 1403 } 1404 } 1405 } 1406 1407 /** 1408 * Called when the fragment is visible to the user and actively running. 1409 * This is generally 1410 * tied to {@link Activity#onResume() Activity.onResume} of the containing 1411 * Activity's lifecycle. 1412 */ 1413 @CallSuper 1414 public void onResume() { 1415 mCalled = true; 1416 } 1417 1418 /** 1419 * Called to ask the fragment to save its current dynamic state, so it 1420 * can later be reconstructed in a new instance of its process is 1421 * restarted. If a new instance of the fragment later needs to be 1422 * created, the data you place in the Bundle here will be available 1423 * in the Bundle given to {@link #onCreate(Bundle)}, 1424 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}, and 1425 * {@link #onActivityCreated(Bundle)}. 1426 * 1427 * <p>This corresponds to {@link Activity#onSaveInstanceState(Bundle) 1428 * Activity.onSaveInstanceState(Bundle)} and most of the discussion there 1429 * applies here as well. Note however: <em>this method may be called 1430 * at any time before {@link #onDestroy()}</em>. There are many situations 1431 * where a fragment may be mostly torn down (such as when placed on the 1432 * back stack with no UI showing), but its state will not be saved until 1433 * its owning activity actually needs to save its state. 1434 * 1435 * @param outState Bundle in which to place your saved state. 1436 */ 1437 public void onSaveInstanceState(Bundle outState) { 1438 } 1439 1440 /** 1441 * Called when the Fragment's activity changes from fullscreen mode to multi-window mode and 1442 * visa-versa. This is generally tied to {@link Activity#onMultiWindowModeChanged} of the 1443 * containing Activity. 1444 * 1445 * @param isInMultiWindowMode True if the activity is in multi-window mode. 1446 */ 1447 public void onMultiWindowModeChanged(boolean isInMultiWindowMode) { 1448 } 1449 1450 /** 1451 * Called by the system when the activity changes to and from picture-in-picture mode. This is 1452 * generally tied to {@link Activity#onPictureInPictureModeChanged} of the containing Activity. 1453 * 1454 * @param isInPictureInPictureMode True if the activity is in picture-in-picture mode. 1455 */ 1456 public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) { 1457 } 1458 1459 @Override 1460 @CallSuper 1461 public void onConfigurationChanged(Configuration newConfig) { 1462 mCalled = true; 1463 } 1464 1465 /** 1466 * Called when the Fragment is no longer resumed. This is generally 1467 * tied to {@link Activity#onPause() Activity.onPause} of the containing 1468 * Activity's lifecycle. 1469 */ 1470 @CallSuper 1471 public void onPause() { 1472 mCalled = true; 1473 } 1474 1475 /** 1476 * Called when the Fragment is no longer started. This is generally 1477 * tied to {@link Activity#onStop() Activity.onStop} of the containing 1478 * Activity's lifecycle. 1479 */ 1480 @CallSuper 1481 public void onStop() { 1482 mCalled = true; 1483 } 1484 1485 @Override 1486 @CallSuper 1487 public void onLowMemory() { 1488 mCalled = true; 1489 } 1490 1491 /** 1492 * Called when the view previously created by {@link #onCreateView} has 1493 * been detached from the fragment. The next time the fragment needs 1494 * to be displayed, a new view will be created. This is called 1495 * after {@link #onStop()} and before {@link #onDestroy()}. It is called 1496 * <em>regardless</em> of whether {@link #onCreateView} returned a 1497 * non-null view. Internally it is called after the view's state has 1498 * been saved but before it has been removed from its parent. 1499 */ 1500 @CallSuper 1501 public void onDestroyView() { 1502 mCalled = true; 1503 } 1504 1505 /** 1506 * Called when the fragment is no longer in use. This is called 1507 * after {@link #onStop()} and before {@link #onDetach()}. 1508 */ 1509 @CallSuper 1510 public void onDestroy() { 1511 mCalled = true; 1512 //Log.v("foo", "onDestroy: mCheckedForLoaderManager=" + mCheckedForLoaderManager 1513 // + " mLoaderManager=" + mLoaderManager); 1514 if (!mCheckedForLoaderManager) { 1515 mCheckedForLoaderManager = true; 1516 mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false); 1517 } 1518 if (mLoaderManager != null) { 1519 mLoaderManager.doDestroy(); 1520 } 1521 } 1522 1523 /** 1524 * Called by the fragment manager once this fragment has been removed, 1525 * so that we don't have any left-over state if the application decides 1526 * to re-use the instance. This only clears state that the framework 1527 * internally manages, not things the application sets. 1528 */ 1529 void initState() { 1530 mIndex = -1; 1531 mWho = null; 1532 mAdded = false; 1533 mRemoving = false; 1534 mFromLayout = false; 1535 mInLayout = false; 1536 mRestored = false; 1537 mBackStackNesting = 0; 1538 mFragmentManager = null; 1539 mChildFragmentManager = null; 1540 mHost = null; 1541 mFragmentId = 0; 1542 mContainerId = 0; 1543 mTag = null; 1544 mHidden = false; 1545 mDetached = false; 1546 mRetaining = false; 1547 mLoaderManager = null; 1548 mLoadersStarted = false; 1549 mCheckedForLoaderManager = false; 1550 } 1551 1552 /** 1553 * Called when the fragment is no longer attached to its activity. This 1554 * is called after {@link #onDestroy()}. 1555 */ 1556 @CallSuper 1557 public void onDetach() { 1558 mCalled = true; 1559 } 1560 1561 /** 1562 * Initialize the contents of the Fragment host's standard options menu. You 1563 * should place your menu items in to <var>menu</var>. For this method 1564 * to be called, you must have first called {@link #setHasOptionsMenu}. See 1565 * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu} 1566 * for more information. 1567 * 1568 * @param menu The options menu in which you place your items. 1569 * 1570 * @see #setHasOptionsMenu 1571 * @see #onPrepareOptionsMenu 1572 * @see #onOptionsItemSelected 1573 */ 1574 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 1575 } 1576 1577 /** 1578 * Prepare the Fragment host's standard options menu to be displayed. This is 1579 * called right before the menu is shown, every time it is shown. You can 1580 * use this method to efficiently enable/disable items or otherwise 1581 * dynamically modify the contents. See 1582 * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu} 1583 * for more information. 1584 * 1585 * @param menu The options menu as last shown or first initialized by 1586 * onCreateOptionsMenu(). 1587 * 1588 * @see #setHasOptionsMenu 1589 * @see #onCreateOptionsMenu 1590 */ 1591 public void onPrepareOptionsMenu(Menu menu) { 1592 } 1593 1594 /** 1595 * Called when this fragment's option menu items are no longer being 1596 * included in the overall options menu. Receiving this call means that 1597 * the menu needed to be rebuilt, but this fragment's items were not 1598 * included in the newly built menu (its {@link #onCreateOptionsMenu(Menu, MenuInflater)} 1599 * was not called). 1600 */ 1601 public void onDestroyOptionsMenu() { 1602 } 1603 1604 /** 1605 * This hook is called whenever an item in your options menu is selected. 1606 * The default implementation simply returns false to have the normal 1607 * processing happen (calling the item's Runnable or sending a message to 1608 * its Handler as appropriate). You can use this method for any items 1609 * for which you would like to do processing without those other 1610 * facilities. 1611 * 1612 * <p>Derived classes should call through to the base class for it to 1613 * perform the default menu handling. 1614 * 1615 * @param item The menu item that was selected. 1616 * 1617 * @return boolean Return false to allow normal menu processing to 1618 * proceed, true to consume it here. 1619 * 1620 * @see #onCreateOptionsMenu 1621 */ 1622 public boolean onOptionsItemSelected(MenuItem item) { 1623 return false; 1624 } 1625 1626 /** 1627 * This hook is called whenever the options menu is being closed (either by the user canceling 1628 * the menu with the back/menu button, or when an item is selected). 1629 * 1630 * @param menu The options menu as last shown or first initialized by 1631 * onCreateOptionsMenu(). 1632 */ 1633 public void onOptionsMenuClosed(Menu menu) { 1634 } 1635 1636 /** 1637 * Called when a context menu for the {@code view} is about to be shown. 1638 * Unlike {@link #onCreateOptionsMenu}, this will be called every 1639 * time the context menu is about to be shown and should be populated for 1640 * the view (or item inside the view for {@link AdapterView} subclasses, 1641 * this can be found in the {@code menuInfo})). 1642 * <p> 1643 * Use {@link #onContextItemSelected(android.view.MenuItem)} to know when an 1644 * item has been selected. 1645 * <p> 1646 * The default implementation calls up to 1647 * {@link Activity#onCreateContextMenu Activity.onCreateContextMenu}, though 1648 * you can not call this implementation if you don't want that behavior. 1649 * <p> 1650 * It is not safe to hold onto the context menu after this method returns. 1651 * {@inheritDoc} 1652 */ 1653 @Override 1654 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 1655 getActivity().onCreateContextMenu(menu, v, menuInfo); 1656 } 1657 1658 /** 1659 * Registers a context menu to be shown for the given view (multiple views 1660 * can show the context menu). This method will set the 1661 * {@link OnCreateContextMenuListener} on the view to this fragment, so 1662 * {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be 1663 * called when it is time to show the context menu. 1664 * 1665 * @see #unregisterForContextMenu(View) 1666 * @param view The view that should show a context menu. 1667 */ 1668 public void registerForContextMenu(View view) { 1669 view.setOnCreateContextMenuListener(this); 1670 } 1671 1672 /** 1673 * Prevents a context menu to be shown for the given view. This method will 1674 * remove the {@link OnCreateContextMenuListener} on the view. 1675 * 1676 * @see #registerForContextMenu(View) 1677 * @param view The view that should stop showing a context menu. 1678 */ 1679 public void unregisterForContextMenu(View view) { 1680 view.setOnCreateContextMenuListener(null); 1681 } 1682 1683 /** 1684 * This hook is called whenever an item in a context menu is selected. The 1685 * default implementation simply returns false to have the normal processing 1686 * happen (calling the item's Runnable or sending a message to its Handler 1687 * as appropriate). You can use this method for any items for which you 1688 * would like to do processing without those other facilities. 1689 * <p> 1690 * Use {@link MenuItem#getMenuInfo()} to get extra information set by the 1691 * View that added this menu item. 1692 * <p> 1693 * Derived classes should call through to the base class for it to perform 1694 * the default menu handling. 1695 * 1696 * @param item The context menu item that was selected. 1697 * @return boolean Return false to allow normal context menu processing to 1698 * proceed, true to consume it here. 1699 */ 1700 public boolean onContextItemSelected(MenuItem item) { 1701 return false; 1702 } 1703 1704 /** 1705 * When custom transitions are used with Fragments, the enter transition callback 1706 * is called when this Fragment is attached or detached when not popping the back stack. 1707 * 1708 * @param callback Used to manipulate the shared element transitions on this Fragment 1709 * when added not as a pop from the back stack. 1710 */ 1711 public void setEnterSharedElementCallback(SharedElementCallback callback) { 1712 ensureAnimationInfo().mEnterTransitionCallback = callback; 1713 } 1714 1715 /** 1716 * When custom transitions are used with Fragments, the exit transition callback 1717 * is called when this Fragment is attached or detached when popping the back stack. 1718 * 1719 * @param callback Used to manipulate the shared element transitions on this Fragment 1720 * when added as a pop from the back stack. 1721 */ 1722 public void setExitSharedElementCallback(SharedElementCallback callback) { 1723 ensureAnimationInfo().mExitTransitionCallback = callback; 1724 } 1725 1726 /** 1727 * Sets the Transition that will be used to move Views into the initial scene. The entering 1728 * Views will be those that are regular Views or ViewGroups that have 1729 * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 1730 * {@link android.transition.Visibility} as entering is governed by changing visibility from 1731 * {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null, 1732 * entering Views will remain unaffected. 1733 * 1734 * @param transition The Transition to use to move Views into the initial Scene. 1735 */ 1736 public void setEnterTransition(Object transition) { 1737 ensureAnimationInfo().mEnterTransition = transition; 1738 } 1739 1740 /** 1741 * Returns the Transition that will be used to move Views into the initial scene. The entering 1742 * Views will be those that are regular Views or ViewGroups that have 1743 * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 1744 * {@link android.transition.Visibility} as entering is governed by changing visibility from 1745 * {@link View#INVISIBLE} to {@link View#VISIBLE}. 1746 * 1747 * @return the Transition to use to move Views into the initial Scene. 1748 */ 1749 public Object getEnterTransition() { 1750 if (mAnimationInfo == null) { 1751 return null; 1752 } 1753 return mAnimationInfo.mEnterTransition; 1754 } 1755 1756 /** 1757 * Sets the Transition that will be used to move Views out of the scene when the Fragment is 1758 * preparing to be removed, hidden, or detached because of popping the back stack. The exiting 1759 * Views will be those that are regular Views or ViewGroups that have 1760 * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 1761 * {@link android.transition.Visibility} as entering is governed by changing visibility from 1762 * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null, 1763 * entering Views will remain unaffected. If nothing is set, the default will be to 1764 * use the same value as set in {@link #setEnterTransition(Object)}. 1765 * 1766 * @param transition The Transition to use to move Views out of the Scene when the Fragment 1767 * is preparing to close. <code>transition</code> must be an 1768 * android.transition.Transition. 1769 */ 1770 public void setReturnTransition(Object transition) { 1771 ensureAnimationInfo().mReturnTransition = transition; 1772 } 1773 1774 /** 1775 * Returns the Transition that will be used to move Views out of the scene when the Fragment is 1776 * preparing to be removed, hidden, or detached because of popping the back stack. The exiting 1777 * Views will be those that are regular Views or ViewGroups that have 1778 * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 1779 * {@link android.transition.Visibility} as entering is governed by changing visibility from 1780 * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null, 1781 * entering Views will remain unaffected. 1782 * 1783 * @return the Transition to use to move Views out of the Scene when the Fragment 1784 * is preparing to close. 1785 */ 1786 public Object getReturnTransition() { 1787 if (mAnimationInfo == null) { 1788 return null; 1789 } 1790 return mAnimationInfo.mReturnTransition == USE_DEFAULT_TRANSITION ? getEnterTransition() 1791 : mAnimationInfo.mReturnTransition; 1792 } 1793 1794 /** 1795 * Sets the Transition that will be used to move Views out of the scene when the 1796 * fragment is removed, hidden, or detached when not popping the back stack. 1797 * The exiting Views will be those that are regular Views or ViewGroups that 1798 * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 1799 * {@link android.transition.Visibility} as exiting is governed by changing visibility 1800 * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will 1801 * remain unaffected. 1802 * 1803 * @param transition The Transition to use to move Views out of the Scene when the Fragment 1804 * is being closed not due to popping the back stack. <code>transition</code> 1805 * must be an android.transition.Transition. 1806 */ 1807 public void setExitTransition(Object transition) { 1808 ensureAnimationInfo().mExitTransition = transition; 1809 } 1810 1811 /** 1812 * Returns the Transition that will be used to move Views out of the scene when the 1813 * fragment is removed, hidden, or detached when not popping the back stack. 1814 * The exiting Views will be those that are regular Views or ViewGroups that 1815 * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend 1816 * {@link android.transition.Visibility} as exiting is governed by changing visibility 1817 * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will 1818 * remain unaffected. 1819 * 1820 * @return the Transition to use to move Views out of the Scene when the Fragment 1821 * is being closed not due to popping the back stack. 1822 */ 1823 public Object getExitTransition() { 1824 if (mAnimationInfo == null) { 1825 return null; 1826 } 1827 return mAnimationInfo.mExitTransition; 1828 } 1829 1830 /** 1831 * Sets the Transition that will be used to move Views in to the scene when returning due 1832 * to popping a back stack. The entering Views will be those that are regular Views 1833 * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions 1834 * will extend {@link android.transition.Visibility} as exiting is governed by changing 1835 * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, 1836 * the views will remain unaffected. If nothing is set, the default will be to use the same 1837 * transition as {@link #setExitTransition(Object)}. 1838 * 1839 * @param transition The Transition to use to move Views into the scene when reentering from a 1840 * previously-started Activity. <code>transition</code> 1841 * must be an android.transition.Transition. 1842 */ 1843 public void setReenterTransition(Object transition) { 1844 ensureAnimationInfo().mReenterTransition = transition; 1845 } 1846 1847 /** 1848 * Returns the Transition that will be used to move Views in to the scene when returning due 1849 * to popping a back stack. The entering Views will be those that are regular Views 1850 * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions 1851 * will extend {@link android.transition.Visibility} as exiting is governed by changing 1852 * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, 1853 * the views will remain unaffected. If nothing is set, the default will be to use the same 1854 * transition as {@link #setExitTransition(Object)}. 1855 * 1856 * @return the Transition to use to move Views into the scene when reentering from a 1857 * previously-started Activity. 1858 */ 1859 public Object getReenterTransition() { 1860 if (mAnimationInfo == null) { 1861 return null; 1862 } 1863 return mAnimationInfo.mReenterTransition == USE_DEFAULT_TRANSITION ? getExitTransition() 1864 : mAnimationInfo.mReenterTransition; 1865 } 1866 1867 /** 1868 * Sets the Transition that will be used for shared elements transferred into the content 1869 * Scene. Typical Transitions will affect size and location, such as 1870 * {@link android.transition.ChangeBounds}. A null 1871 * value will cause transferred shared elements to blink to the final position. 1872 * 1873 * @param transition The Transition to use for shared elements transferred into the content 1874 * Scene. <code>transition</code> must be an android.transition.Transition. 1875 */ 1876 public void setSharedElementEnterTransition(Object transition) { 1877 ensureAnimationInfo().mSharedElementEnterTransition = transition; 1878 } 1879 1880 /** 1881 * Returns the Transition that will be used for shared elements transferred into the content 1882 * Scene. Typical Transitions will affect size and location, such as 1883 * {@link android.transition.ChangeBounds}. A null 1884 * value will cause transferred shared elements to blink to the final position. 1885 * 1886 * @return The Transition to use for shared elements transferred into the content 1887 * Scene. 1888 */ 1889 public Object getSharedElementEnterTransition() { 1890 if (mAnimationInfo == null) { 1891 return null; 1892 } 1893 return mAnimationInfo.mSharedElementEnterTransition; 1894 } 1895 1896 /** 1897 * Sets the Transition that will be used for shared elements transferred back during a 1898 * pop of the back stack. This Transition acts in the leaving Fragment. 1899 * Typical Transitions will affect size and location, such as 1900 * {@link android.transition.ChangeBounds}. A null 1901 * value will cause transferred shared elements to blink to the final position. 1902 * If no value is set, the default will be to use the same value as 1903 * {@link #setSharedElementEnterTransition(Object)}. 1904 * 1905 * @param transition The Transition to use for shared elements transferred out of the content 1906 * Scene. <code>transition</code> must be an android.transition.Transition. 1907 */ 1908 public void setSharedElementReturnTransition(Object transition) { 1909 ensureAnimationInfo().mSharedElementReturnTransition = transition; 1910 } 1911 1912 /** 1913 * Return the Transition that will be used for shared elements transferred back during a 1914 * pop of the back stack. This Transition acts in the leaving Fragment. 1915 * Typical Transitions will affect size and location, such as 1916 * {@link android.transition.ChangeBounds}. A null 1917 * value will cause transferred shared elements to blink to the final position. 1918 * If no value is set, the default will be to use the same value as 1919 * {@link #setSharedElementEnterTransition(Object)}. 1920 * 1921 * @return The Transition to use for shared elements transferred out of the content 1922 * Scene. 1923 */ 1924 public Object getSharedElementReturnTransition() { 1925 if (mAnimationInfo == null) { 1926 return null; 1927 } 1928 return mAnimationInfo.mSharedElementReturnTransition == USE_DEFAULT_TRANSITION 1929 ? getSharedElementEnterTransition() 1930 : mAnimationInfo.mSharedElementReturnTransition; 1931 } 1932 1933 /** 1934 * Sets whether the the exit transition and enter transition overlap or not. 1935 * When true, the enter transition will start as soon as possible. When false, the 1936 * enter transition will wait until the exit transition completes before starting. 1937 * 1938 * @param allow true to start the enter transition when possible or false to 1939 * wait until the exiting transition completes. 1940 */ 1941 public void setAllowEnterTransitionOverlap(boolean allow) { 1942 ensureAnimationInfo().mAllowEnterTransitionOverlap = allow; 1943 } 1944 1945 /** 1946 * Returns whether the the exit transition and enter transition overlap or not. 1947 * When true, the enter transition will start as soon as possible. When false, the 1948 * enter transition will wait until the exit transition completes before starting. 1949 * 1950 * @return true when the enter transition should start as soon as possible or false to 1951 * when it should wait until the exiting transition completes. 1952 */ 1953 public boolean getAllowEnterTransitionOverlap() { 1954 return (mAnimationInfo == null || mAnimationInfo.mAllowEnterTransitionOverlap == null) 1955 ? true : mAnimationInfo.mAllowEnterTransitionOverlap; 1956 } 1957 1958 /** 1959 * Sets whether the the return transition and reenter transition overlap or not. 1960 * When true, the reenter transition will start as soon as possible. When false, the 1961 * reenter transition will wait until the return transition completes before starting. 1962 * 1963 * @param allow true to start the reenter transition when possible or false to wait until the 1964 * return transition completes. 1965 */ 1966 public void setAllowReturnTransitionOverlap(boolean allow) { 1967 ensureAnimationInfo().mAllowReturnTransitionOverlap = allow; 1968 } 1969 1970 /** 1971 * Returns whether the the return transition and reenter transition overlap or not. 1972 * When true, the reenter transition will start as soon as possible. When false, the 1973 * reenter transition will wait until the return transition completes before starting. 1974 * 1975 * @return true to start the reenter transition when possible or false to wait until the 1976 * return transition completes. 1977 */ 1978 public boolean getAllowReturnTransitionOverlap() { 1979 return (mAnimationInfo == null || mAnimationInfo.mAllowReturnTransitionOverlap == null) 1980 ? true : mAnimationInfo.mAllowReturnTransitionOverlap; 1981 } 1982 1983 /** 1984 * Postpone the entering Fragment transition until {@link #startPostponedEnterTransition()} 1985 * or {@link FragmentManager#executePendingTransactions()} has been called. 1986 * <p> 1987 * This method gives the Fragment the ability to delay Fragment animations 1988 * until all data is loaded. Until then, the added, shown, and 1989 * attached Fragments will be INVISIBLE and removed, hidden, and detached Fragments won't 1990 * be have their Views removed. The transaction runs when all postponed added Fragments in the 1991 * transaction have called {@link #startPostponedEnterTransition()}. 1992 * <p> 1993 * This method should be called before being added to the FragmentTransaction or 1994 * in {@link #onCreate(Bundle), {@link #onAttach(Context)}, or 1995 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}}. 1996 * {@link #startPostponedEnterTransition()} must be called to allow the Fragment to 1997 * start the transitions. 1998 * <p> 1999 * When a FragmentTransaction is started that may affect a postponed FragmentTransaction, 2000 * based on which containers are in their operations, the postponed FragmentTransaction 2001 * will have its start triggered. The early triggering may result in faulty or nonexistent 2002 * animations in the postponed transaction. FragmentTransactions that operate only on 2003 * independent containers will not interfere with each other's postponement. 2004 * <p> 2005 * Calling postponeEnterTransition on Fragments with a null View will not postpone the 2006 * transition. Likewise, postponement only works if FragmentTransaction optimizations are 2007 * enabled. 2008 * 2009 * @see Activity#postponeEnterTransition() 2010 * @see FragmentTransaction#setAllowOptimization(boolean) 2011 */ 2012 public void postponeEnterTransition() { 2013 ensureAnimationInfo().mEnterTransitionPostponed = true; 2014 } 2015 2016 /** 2017 * Begin postponed transitions after {@link #postponeEnterTransition()} was called. 2018 * If postponeEnterTransition() was called, you must call startPostponedEnterTransition() 2019 * or {@link FragmentManager#executePendingTransactions()} to complete the FragmentTransaction. 2020 * If postponement was interrupted with {@link FragmentManager#executePendingTransactions()}, 2021 * before {@code startPostponedEnterTransition()}, animations may not run or may execute 2022 * improperly. 2023 * 2024 * @see Activity#startPostponedEnterTransition() 2025 */ 2026 public void startPostponedEnterTransition() { 2027 if (mFragmentManager == null || mFragmentManager.mHost == null) { 2028 ensureAnimationInfo().mEnterTransitionPostponed = false; 2029 } else if (Looper.myLooper() != mFragmentManager.mHost.getHandler().getLooper()) { 2030 mFragmentManager.mHost.getHandler().postAtFrontOfQueue(new Runnable() { 2031 @Override 2032 public void run() { 2033 callStartTransitionListener(); 2034 } 2035 }); 2036 } else { 2037 callStartTransitionListener(); 2038 } 2039 } 2040 2041 /** 2042 * Calls the start transition listener. This must be called on the UI thread. 2043 */ 2044 private void callStartTransitionListener() { 2045 final OnStartEnterTransitionListener listener; 2046 if (mAnimationInfo == null) { 2047 listener = null; 2048 } else { 2049 mAnimationInfo.mEnterTransitionPostponed = false; 2050 listener = mAnimationInfo.mStartEnterTransitionListener; 2051 mAnimationInfo.mStartEnterTransitionListener = null; 2052 } 2053 if (listener != null) { 2054 listener.onStartEnterTransition(); 2055 } 2056 } 2057 2058 /** 2059 * Print the Fragments's state into the given stream. 2060 * 2061 * @param prefix Text to print at the front of each line. 2062 * @param fd The raw file descriptor that the dump is being sent to. 2063 * @param writer The PrintWriter to which you should dump your state. This will be 2064 * closed for you after you return. 2065 * @param args additional arguments to the dump request. 2066 */ 2067 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { 2068 writer.print(prefix); writer.print("mFragmentId=#"); 2069 writer.print(Integer.toHexString(mFragmentId)); 2070 writer.print(" mContainerId=#"); 2071 writer.print(Integer.toHexString(mContainerId)); 2072 writer.print(" mTag="); writer.println(mTag); 2073 writer.print(prefix); writer.print("mState="); writer.print(mState); 2074 writer.print(" mIndex="); writer.print(mIndex); 2075 writer.print(" mWho="); writer.print(mWho); 2076 writer.print(" mBackStackNesting="); writer.println(mBackStackNesting); 2077 writer.print(prefix); writer.print("mAdded="); writer.print(mAdded); 2078 writer.print(" mRemoving="); writer.print(mRemoving); 2079 writer.print(" mFromLayout="); writer.print(mFromLayout); 2080 writer.print(" mInLayout="); writer.println(mInLayout); 2081 writer.print(prefix); writer.print("mHidden="); writer.print(mHidden); 2082 writer.print(" mDetached="); writer.print(mDetached); 2083 writer.print(" mMenuVisible="); writer.print(mMenuVisible); 2084 writer.print(" mHasMenu="); writer.println(mHasMenu); 2085 writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance); 2086 writer.print(" mRetaining="); writer.print(mRetaining); 2087 writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint); 2088 if (mFragmentManager != null) { 2089 writer.print(prefix); writer.print("mFragmentManager="); 2090 writer.println(mFragmentManager); 2091 } 2092 if (mHost != null) { 2093 writer.print(prefix); writer.print("mHost="); 2094 writer.println(mHost); 2095 } 2096 if (mParentFragment != null) { 2097 writer.print(prefix); writer.print("mParentFragment="); 2098 writer.println(mParentFragment); 2099 } 2100 if (mArguments != null) { 2101 writer.print(prefix); writer.print("mArguments="); writer.println(mArguments); 2102 } 2103 if (mSavedFragmentState != null) { 2104 writer.print(prefix); writer.print("mSavedFragmentState="); 2105 writer.println(mSavedFragmentState); 2106 } 2107 if (mSavedViewState != null) { 2108 writer.print(prefix); writer.print("mSavedViewState="); 2109 writer.println(mSavedViewState); 2110 } 2111 if (mTarget != null) { 2112 writer.print(prefix); writer.print("mTarget="); writer.print(mTarget); 2113 writer.print(" mTargetRequestCode="); 2114 writer.println(mTargetRequestCode); 2115 } 2116 if (getNextAnim() != 0) { 2117 writer.print(prefix); writer.print("mNextAnim="); writer.println(getNextAnim()); 2118 } 2119 if (mContainer != null) { 2120 writer.print(prefix); writer.print("mContainer="); writer.println(mContainer); 2121 } 2122 if (mView != null) { 2123 writer.print(prefix); writer.print("mView="); writer.println(mView); 2124 } 2125 if (mInnerView != null) { 2126 writer.print(prefix); writer.print("mInnerView="); writer.println(mView); 2127 } 2128 if (getAnimatingAway() != null) { 2129 writer.print(prefix); 2130 writer.print("mAnimatingAway="); 2131 writer.println(getAnimatingAway()); 2132 writer.print(prefix); 2133 writer.print("mStateAfterAnimating="); 2134 writer.println(getStateAfterAnimating()); 2135 } 2136 if (mLoaderManager != null) { 2137 writer.print(prefix); writer.println("Loader Manager:"); 2138 mLoaderManager.dump(prefix + " ", fd, writer, args); 2139 } 2140 if (mChildFragmentManager != null) { 2141 writer.print(prefix); writer.println("Child " + mChildFragmentManager + ":"); 2142 mChildFragmentManager.dump(prefix + " ", fd, writer, args); 2143 } 2144 } 2145 2146 Fragment findFragmentByWho(String who) { 2147 if (who.equals(mWho)) { 2148 return this; 2149 } 2150 if (mChildFragmentManager != null) { 2151 return mChildFragmentManager.findFragmentByWho(who); 2152 } 2153 return null; 2154 } 2155 2156 void instantiateChildFragmentManager() { 2157 if (mHost == null) { 2158 throw new IllegalStateException("Fragment has not been attached yet."); 2159 } 2160 mChildFragmentManager = new FragmentManagerImpl(); 2161 mChildFragmentManager.attachController(mHost, new FragmentContainer() { 2162 @Override 2163 @Nullable 2164 public View onFindViewById(int id) { 2165 if (mView == null) { 2166 throw new IllegalStateException("Fragment does not have a view"); 2167 } 2168 return mView.findViewById(id); 2169 } 2170 2171 @Override 2172 public boolean onHasView() { 2173 return (mView != null); 2174 } 2175 }, this); 2176 } 2177 2178 void performCreate(Bundle savedInstanceState) { 2179 if (mChildFragmentManager != null) { 2180 mChildFragmentManager.noteStateNotSaved(); 2181 } 2182 mState = CREATED; 2183 mCalled = false; 2184 onCreate(savedInstanceState); 2185 if (!mCalled) { 2186 throw new SuperNotCalledException("Fragment " + this 2187 + " did not call through to super.onCreate()"); 2188 } 2189 } 2190 2191 View performCreateView(LayoutInflater inflater, ViewGroup container, 2192 Bundle savedInstanceState) { 2193 if (mChildFragmentManager != null) { 2194 mChildFragmentManager.noteStateNotSaved(); 2195 } 2196 mPerformedCreateView = true; 2197 return onCreateView(inflater, container, savedInstanceState); 2198 } 2199 2200 void performActivityCreated(Bundle savedInstanceState) { 2201 if (mChildFragmentManager != null) { 2202 mChildFragmentManager.noteStateNotSaved(); 2203 } 2204 mState = ACTIVITY_CREATED; 2205 mCalled = false; 2206 onActivityCreated(savedInstanceState); 2207 if (!mCalled) { 2208 throw new SuperNotCalledException("Fragment " + this 2209 + " did not call through to super.onActivityCreated()"); 2210 } 2211 if (mChildFragmentManager != null) { 2212 mChildFragmentManager.dispatchActivityCreated(); 2213 } 2214 } 2215 2216 void performStart() { 2217 if (mChildFragmentManager != null) { 2218 mChildFragmentManager.noteStateNotSaved(); 2219 mChildFragmentManager.execPendingActions(); 2220 } 2221 mState = STARTED; 2222 mCalled = false; 2223 onStart(); 2224 if (!mCalled) { 2225 throw new SuperNotCalledException("Fragment " + this 2226 + " did not call through to super.onStart()"); 2227 } 2228 if (mChildFragmentManager != null) { 2229 mChildFragmentManager.dispatchStart(); 2230 } 2231 if (mLoaderManager != null) { 2232 mLoaderManager.doReportStart(); 2233 } 2234 } 2235 2236 void performResume() { 2237 if (mChildFragmentManager != null) { 2238 mChildFragmentManager.noteStateNotSaved(); 2239 mChildFragmentManager.execPendingActions(); 2240 } 2241 mState = RESUMED; 2242 mCalled = false; 2243 onResume(); 2244 if (!mCalled) { 2245 throw new SuperNotCalledException("Fragment " + this 2246 + " did not call through to super.onResume()"); 2247 } 2248 if (mChildFragmentManager != null) { 2249 mChildFragmentManager.dispatchResume(); 2250 mChildFragmentManager.execPendingActions(); 2251 } 2252 } 2253 2254 void performMultiWindowModeChanged(boolean isInMultiWindowMode) { 2255 onMultiWindowModeChanged(isInMultiWindowMode); 2256 if (mChildFragmentManager != null) { 2257 mChildFragmentManager.dispatchMultiWindowModeChanged(isInMultiWindowMode); 2258 } 2259 } 2260 2261 void performPictureInPictureModeChanged(boolean isInPictureInPictureMode) { 2262 onPictureInPictureModeChanged(isInPictureInPictureMode); 2263 if (mChildFragmentManager != null) { 2264 mChildFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode); 2265 } 2266 } 2267 2268 void performConfigurationChanged(Configuration newConfig) { 2269 onConfigurationChanged(newConfig); 2270 if (mChildFragmentManager != null) { 2271 mChildFragmentManager.dispatchConfigurationChanged(newConfig); 2272 } 2273 } 2274 2275 void performLowMemory() { 2276 onLowMemory(); 2277 if (mChildFragmentManager != null) { 2278 mChildFragmentManager.dispatchLowMemory(); 2279 } 2280 } 2281 2282 /* 2283 void performTrimMemory(int level) { 2284 onTrimMemory(level); 2285 if (mChildFragmentManager != null) { 2286 mChildFragmentManager.dispatchTrimMemory(level); 2287 } 2288 } 2289 */ 2290 2291 boolean performCreateOptionsMenu(Menu menu, MenuInflater inflater) { 2292 boolean show = false; 2293 if (!mHidden) { 2294 if (mHasMenu && mMenuVisible) { 2295 show = true; 2296 onCreateOptionsMenu(menu, inflater); 2297 } 2298 if (mChildFragmentManager != null) { 2299 show |= mChildFragmentManager.dispatchCreateOptionsMenu(menu, inflater); 2300 } 2301 } 2302 return show; 2303 } 2304 2305 boolean performPrepareOptionsMenu(Menu menu) { 2306 boolean show = false; 2307 if (!mHidden) { 2308 if (mHasMenu && mMenuVisible) { 2309 show = true; 2310 onPrepareOptionsMenu(menu); 2311 } 2312 if (mChildFragmentManager != null) { 2313 show |= mChildFragmentManager.dispatchPrepareOptionsMenu(menu); 2314 } 2315 } 2316 return show; 2317 } 2318 2319 boolean performOptionsItemSelected(MenuItem item) { 2320 if (!mHidden) { 2321 if (mHasMenu && mMenuVisible) { 2322 if (onOptionsItemSelected(item)) { 2323 return true; 2324 } 2325 } 2326 if (mChildFragmentManager != null) { 2327 if (mChildFragmentManager.dispatchOptionsItemSelected(item)) { 2328 return true; 2329 } 2330 } 2331 } 2332 return false; 2333 } 2334 2335 boolean performContextItemSelected(MenuItem item) { 2336 if (!mHidden) { 2337 if (onContextItemSelected(item)) { 2338 return true; 2339 } 2340 if (mChildFragmentManager != null) { 2341 if (mChildFragmentManager.dispatchContextItemSelected(item)) { 2342 return true; 2343 } 2344 } 2345 } 2346 return false; 2347 } 2348 2349 void performOptionsMenuClosed(Menu menu) { 2350 if (!mHidden) { 2351 if (mHasMenu && mMenuVisible) { 2352 onOptionsMenuClosed(menu); 2353 } 2354 if (mChildFragmentManager != null) { 2355 mChildFragmentManager.dispatchOptionsMenuClosed(menu); 2356 } 2357 } 2358 } 2359 2360 void performSaveInstanceState(Bundle outState) { 2361 onSaveInstanceState(outState); 2362 if (mChildFragmentManager != null) { 2363 Parcelable p = mChildFragmentManager.saveAllState(); 2364 if (p != null) { 2365 outState.putParcelable(FragmentActivity.FRAGMENTS_TAG, p); 2366 } 2367 } 2368 } 2369 2370 void performPause() { 2371 if (mChildFragmentManager != null) { 2372 mChildFragmentManager.dispatchPause(); 2373 } 2374 mState = STARTED; 2375 mCalled = false; 2376 onPause(); 2377 if (!mCalled) { 2378 throw new SuperNotCalledException("Fragment " + this 2379 + " did not call through to super.onPause()"); 2380 } 2381 } 2382 2383 void performStop() { 2384 if (mChildFragmentManager != null) { 2385 mChildFragmentManager.dispatchStop(); 2386 } 2387 mState = STOPPED; 2388 mCalled = false; 2389 onStop(); 2390 if (!mCalled) { 2391 throw new SuperNotCalledException("Fragment " + this 2392 + " did not call through to super.onStop()"); 2393 } 2394 } 2395 2396 void performReallyStop() { 2397 if (mChildFragmentManager != null) { 2398 mChildFragmentManager.dispatchReallyStop(); 2399 } 2400 mState = ACTIVITY_CREATED; 2401 if (mLoadersStarted) { 2402 mLoadersStarted = false; 2403 if (!mCheckedForLoaderManager) { 2404 mCheckedForLoaderManager = true; 2405 mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false); 2406 } 2407 if (mLoaderManager != null) { 2408 if (mHost.getRetainLoaders()) { 2409 mLoaderManager.doRetain(); 2410 } else { 2411 mLoaderManager.doStop(); 2412 } 2413 } 2414 } 2415 } 2416 2417 void performDestroyView() { 2418 if (mChildFragmentManager != null) { 2419 mChildFragmentManager.dispatchDestroyView(); 2420 } 2421 mState = CREATED; 2422 mCalled = false; 2423 onDestroyView(); 2424 if (!mCalled) { 2425 throw new SuperNotCalledException("Fragment " + this 2426 + " did not call through to super.onDestroyView()"); 2427 } 2428 if (mLoaderManager != null) { 2429 mLoaderManager.doReportNextStart(); 2430 } 2431 mPerformedCreateView = false; 2432 } 2433 2434 void performDestroy() { 2435 if (mChildFragmentManager != null) { 2436 mChildFragmentManager.dispatchDestroy(); 2437 } 2438 mState = INITIALIZING; 2439 mCalled = false; 2440 onDestroy(); 2441 if (!mCalled) { 2442 throw new SuperNotCalledException("Fragment " + this 2443 + " did not call through to super.onDestroy()"); 2444 } 2445 mChildFragmentManager = null; 2446 } 2447 2448 void performDetach() { 2449 mCalled = false; 2450 onDetach(); 2451 if (!mCalled) { 2452 throw new SuperNotCalledException("Fragment " + this 2453 + " did not call through to super.onDetach()"); 2454 } 2455 2456 // Destroy the child FragmentManager if we still have it here. 2457 // We won't unless we're retaining our instance and if we do, 2458 // our child FragmentManager instance state will have already been saved. 2459 if (mChildFragmentManager != null) { 2460 if (!mRetaining) { 2461 throw new IllegalStateException("Child FragmentManager of " + this + " was not " 2462 + " destroyed and this fragment is not retaining instance"); 2463 } 2464 mChildFragmentManager.dispatchDestroy(); 2465 mChildFragmentManager = null; 2466 } 2467 } 2468 2469 void setOnStartEnterTransitionListener(OnStartEnterTransitionListener listener) { 2470 ensureAnimationInfo(); 2471 if (listener == mAnimationInfo.mStartEnterTransitionListener) { 2472 return; 2473 } 2474 if (listener != null && mAnimationInfo.mStartEnterTransitionListener != null) { 2475 throw new IllegalStateException("Trying to set a replacement " 2476 + "startPostponedEnterTransition on " + this); 2477 } 2478 if (mAnimationInfo.mEnterTransitionPostponed) { 2479 mAnimationInfo.mStartEnterTransitionListener = listener; 2480 } 2481 if (listener != null) { 2482 listener.startListening(); 2483 } 2484 } 2485 2486 private AnimationInfo ensureAnimationInfo() { 2487 if (mAnimationInfo == null) { 2488 mAnimationInfo = new AnimationInfo(); 2489 } 2490 return mAnimationInfo; 2491 } 2492 2493 int getNextAnim() { 2494 if (mAnimationInfo == null) { 2495 return 0; 2496 } 2497 return mAnimationInfo.mNextAnim; 2498 } 2499 2500 void setNextAnim(int animResourceId) { 2501 if (mAnimationInfo == null && animResourceId == 0) { 2502 return; // no change! 2503 } 2504 ensureAnimationInfo().mNextAnim = animResourceId; 2505 } 2506 2507 int getNextTransition() { 2508 if (mAnimationInfo == null) { 2509 return 0; 2510 } 2511 return mAnimationInfo.mNextTransition; 2512 } 2513 2514 void setNextTransition(int nextTransition, int nextTransitionStyle) { 2515 if (mAnimationInfo == null && nextTransition == 0 && nextTransitionStyle == 0) { 2516 return; // no change! 2517 } 2518 ensureAnimationInfo(); 2519 mAnimationInfo.mNextTransition = nextTransition; 2520 mAnimationInfo.mNextTransitionStyle = nextTransitionStyle; 2521 } 2522 2523 int getNextTransitionStyle() { 2524 if (mAnimationInfo == null) { 2525 return 0; 2526 } 2527 return mAnimationInfo.mNextTransitionStyle; 2528 } 2529 2530 SharedElementCallback getEnterTransitionCallback() { 2531 if (mAnimationInfo == null) { 2532 return null; 2533 } 2534 return mAnimationInfo.mEnterTransitionCallback; 2535 } 2536 2537 SharedElementCallback getExitTransitionCallback() { 2538 if (mAnimationInfo == null) { 2539 return null; 2540 } 2541 return mAnimationInfo.mExitTransitionCallback; 2542 } 2543 2544 View getAnimatingAway() { 2545 if (mAnimationInfo == null) { 2546 return null; 2547 } 2548 return mAnimationInfo.mAnimatingAway; 2549 } 2550 2551 void setAnimatingAway(View view) { 2552 ensureAnimationInfo().mAnimatingAway = view; 2553 } 2554 2555 int getStateAfterAnimating() { 2556 if (mAnimationInfo == null) { 2557 return 0; 2558 } 2559 return mAnimationInfo.mStateAfterAnimating; 2560 } 2561 2562 void setStateAfterAnimating(int state) { 2563 ensureAnimationInfo().mStateAfterAnimating = state; 2564 } 2565 2566 boolean isPostponed() { 2567 if (mAnimationInfo == null) { 2568 return false; 2569 } 2570 return mAnimationInfo.mEnterTransitionPostponed; 2571 } 2572 2573 boolean isHideReplaced() { 2574 if (mAnimationInfo == null) { 2575 return false; 2576 } 2577 return mAnimationInfo.mIsHideReplaced; 2578 } 2579 2580 void setHideReplaced(boolean replaced) { 2581 ensureAnimationInfo().mIsHideReplaced = replaced; 2582 } 2583 2584 /** 2585 * Used internally to be notified when {@link #startPostponedEnterTransition()} has 2586 * been called. This listener will only be called once and then be removed from the 2587 * listeners. 2588 */ 2589 interface OnStartEnterTransitionListener { 2590 void onStartEnterTransition(); 2591 void startListening(); 2592 } 2593 2594 /** 2595 * Contains all the animation and transition information for a fragment. This will only 2596 * be instantiated for Fragments that have Views. 2597 */ 2598 static class AnimationInfo { 2599 // Non-null if the fragment's view hierarchy is currently animating away, 2600 // meaning we need to wait a bit on completely destroying it. This is the 2601 // view that is animating. 2602 View mAnimatingAway; 2603 2604 // If mAnimatingAway != null, this is the state we should move to once the 2605 // animation is done. 2606 int mStateAfterAnimating; 2607 2608 // If app has requested a specific animation, this is the one to use. 2609 int mNextAnim; 2610 2611 // If app has requested a specific transition, this is the one to use. 2612 int mNextTransition; 2613 2614 // If app has requested a specific transition style, this is the one to use. 2615 int mNextTransitionStyle; 2616 2617 private Object mEnterTransition = null; 2618 private Object mReturnTransition = USE_DEFAULT_TRANSITION; 2619 private Object mExitTransition = null; 2620 private Object mReenterTransition = USE_DEFAULT_TRANSITION; 2621 private Object mSharedElementEnterTransition = null; 2622 private Object mSharedElementReturnTransition = USE_DEFAULT_TRANSITION; 2623 private Boolean mAllowReturnTransitionOverlap; 2624 private Boolean mAllowEnterTransitionOverlap; 2625 2626 SharedElementCallback mEnterTransitionCallback = null; 2627 SharedElementCallback mExitTransitionCallback = null; 2628 2629 // True when postponeEnterTransition has been called and startPostponeEnterTransition 2630 // hasn't been called yet. 2631 boolean mEnterTransitionPostponed; 2632 2633 // Listener to wait for startPostponeEnterTransition. After being called, it will 2634 // be set to null 2635 OnStartEnterTransitionListener mStartEnterTransitionListener; 2636 2637 // True if the View was hidden, but the transition is handling the hide 2638 boolean mIsHideReplaced; 2639 } 2640} 2641