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