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