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