• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.fragment.app;
18 
19 import android.content.Context;
20 import android.content.res.Configuration;
21 import android.os.Parcelable;
22 import android.util.AttributeSet;
23 import android.view.Menu;
24 import android.view.MenuInflater;
25 import android.view.MenuItem;
26 import android.view.View;
27 
28 import androidx.annotation.Nullable;
29 import androidx.collection.SimpleArrayMap;
30 import androidx.loader.app.LoaderManager;
31 
32 import java.io.FileDescriptor;
33 import java.io.PrintWriter;
34 import java.util.List;
35 
36 /**
37  * Provides integration points with a {@link FragmentManager} for a fragment host.
38  * <p>
39  * It is the responsibility of the host to take care of the Fragment's lifecycle.
40  * The methods provided by {@link FragmentController} are for that purpose.
41  */
42 public class FragmentController {
43     private final FragmentHostCallback<?> mHost;
44 
45     /**
46      * Returns a {@link FragmentController}.
47      */
createController(FragmentHostCallback<?> callbacks)48     public static FragmentController createController(FragmentHostCallback<?> callbacks) {
49         return new FragmentController(callbacks);
50     }
51 
FragmentController(FragmentHostCallback<?> callbacks)52     private FragmentController(FragmentHostCallback<?> callbacks) {
53         mHost = callbacks;
54     }
55 
56     /**
57      * Returns a {@link FragmentManager} for this controller.
58      */
getSupportFragmentManager()59     public FragmentManager getSupportFragmentManager() {
60         return mHost.getFragmentManagerImpl();
61     }
62 
63     /**
64      * Returns a {@link LoaderManager}.
65      *
66      * @deprecated Loaders are managed separately from FragmentController and this now throws an
67      * {@link UnsupportedOperationException}. Use {@link LoaderManager#getInstance} to obtain a
68      * LoaderManager.
69      * @see LoaderManager#getInstance
70      */
71     @Deprecated
getSupportLoaderManager()72     public LoaderManager getSupportLoaderManager() {
73         throw new UnsupportedOperationException("Loaders are managed separately from "
74                 + "FragmentController, use LoaderManager.getInstance() to obtain a LoaderManager.");
75     }
76 
77     /**
78      * Returns a fragment with the given identifier.
79      */
80     @Nullable
findFragmentByWho(String who)81     public Fragment findFragmentByWho(String who) {
82         return mHost.mFragmentManager.findFragmentByWho(who);
83     }
84 
85     /**
86      * Returns the number of active fragments.
87      */
getActiveFragmentsCount()88     public int getActiveFragmentsCount() {
89         return mHost.mFragmentManager.getActiveFragmentCount();
90     }
91 
92     /**
93      * Returns the list of active fragments.
94      */
getActiveFragments(List<Fragment> actives)95     public List<Fragment> getActiveFragments(List<Fragment> actives) {
96         return mHost.mFragmentManager.getActiveFragments();
97     }
98 
99     /**
100      * Attaches the host to the FragmentManager for this controller. The host must be
101      * attached before the FragmentManager can be used to manage Fragments.
102      */
attachHost(Fragment parent)103     public void attachHost(Fragment parent) {
104         mHost.mFragmentManager.attachController(
105                 mHost, mHost /*container*/, parent);
106     }
107 
108     /**
109      * Instantiates a Fragment's view.
110      *
111      * @param parent The parent that the created view will be placed
112      * in; <em>note that this may be null</em>.
113      * @param name Tag name to be inflated.
114      * @param context The context the view is being created in.
115      * @param attrs Inflation attributes as specified in XML file.
116      *
117      * @return view the newly created view
118      */
onCreateView(View parent, String name, Context context, AttributeSet attrs)119     public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
120         return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
121     }
122 
123     /**
124      * Marks the fragment state as unsaved. This allows for "state loss" detection.
125      */
noteStateNotSaved()126     public void noteStateNotSaved() {
127         mHost.mFragmentManager.noteStateNotSaved();
128     }
129 
130     /**
131      * Saves the state for all Fragments.
132      */
saveAllState()133     public Parcelable saveAllState() {
134         return mHost.mFragmentManager.saveAllState();
135     }
136 
137     /**
138      * Restores the saved state for all Fragments. The given Fragment list are Fragment
139      * instances retained across configuration changes.
140      *
141      * @see #retainNonConfig()
142      *
143      * @deprecated use {@link #restoreAllState(Parcelable, FragmentManagerNonConfig)}
144      */
145     @Deprecated
restoreAllState(Parcelable state, List<Fragment> nonConfigList)146     public void restoreAllState(Parcelable state, List<Fragment> nonConfigList) {
147         mHost.mFragmentManager.restoreAllState(state,
148                 new FragmentManagerNonConfig(nonConfigList, null, null));
149     }
150 
151     /**
152      * Restores the saved state for all Fragments. The given FragmentManagerNonConfig are Fragment
153      * instances retained across configuration changes, including nested fragments
154      *
155      * @see #retainNestedNonConfig()
156      */
restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig)157     public void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
158         mHost.mFragmentManager.restoreAllState(state, nonConfig);
159     }
160 
161     /**
162      * Returns a list of Fragments that have opted to retain their instance across
163      * configuration changes.
164      *
165      * @deprecated use {@link #retainNestedNonConfig()} to also track retained
166      *             nested child fragments
167      */
168     @Deprecated
retainNonConfig()169     public List<Fragment> retainNonConfig() {
170         FragmentManagerNonConfig nonconf = mHost.mFragmentManager.retainNonConfig();
171         return nonconf != null ? nonconf.getFragments() : null;
172     }
173 
174     /**
175      * Returns a nested tree of Fragments that have opted to retain their instance across
176      * configuration changes.
177      */
retainNestedNonConfig()178     public FragmentManagerNonConfig retainNestedNonConfig() {
179         return mHost.mFragmentManager.retainNonConfig();
180     }
181 
182     /**
183      * Moves all Fragments managed by the controller's FragmentManager
184      * into the create state.
185      * <p>Call when Fragments should be created.
186      *
187      * @see Fragment#onCreate(Bundle)
188      */
dispatchCreate()189     public void dispatchCreate() {
190         mHost.mFragmentManager.dispatchCreate();
191     }
192 
193     /**
194      * Moves all Fragments managed by the controller's FragmentManager
195      * into the activity created state.
196      * <p>Call when Fragments should be informed their host has been created.
197      *
198      * @see Fragment#onActivityCreated(Bundle)
199      */
dispatchActivityCreated()200     public void dispatchActivityCreated() {
201         mHost.mFragmentManager.dispatchActivityCreated();
202     }
203 
204     /**
205      * Moves all Fragments managed by the controller's FragmentManager
206      * into the start state.
207      * <p>Call when Fragments should be started.
208      *
209      * @see Fragment#onStart()
210      */
dispatchStart()211     public void dispatchStart() {
212         mHost.mFragmentManager.dispatchStart();
213     }
214 
215     /**
216      * Moves all Fragments managed by the controller's FragmentManager
217      * into the resume state.
218      * <p>Call when Fragments should be resumed.
219      *
220      * @see Fragment#onResume()
221      */
dispatchResume()222     public void dispatchResume() {
223         mHost.mFragmentManager.dispatchResume();
224     }
225 
226     /**
227      * Moves all Fragments managed by the controller's FragmentManager
228      * into the pause state.
229      * <p>Call when Fragments should be paused.
230      *
231      * @see Fragment#onPause()
232      */
dispatchPause()233     public void dispatchPause() {
234         mHost.mFragmentManager.dispatchPause();
235     }
236 
237     /**
238      * Moves all Fragments managed by the controller's FragmentManager
239      * into the stop state.
240      * <p>Call when Fragments should be stopped.
241      *
242      * @see Fragment#onStop()
243      */
dispatchStop()244     public void dispatchStop() {
245         mHost.mFragmentManager.dispatchStop();
246     }
247 
248     /**
249      * @deprecated This functionality has been rolled into {@link #dispatchStop()}.
250      */
251     @Deprecated
dispatchReallyStop()252     public void dispatchReallyStop() {
253     }
254 
255     /**
256      * Moves all Fragments managed by the controller's FragmentManager
257      * into the destroy view state.
258      * <p>Call when the Fragment's views should be destroyed.
259      *
260      * @see Fragment#onDestroyView()
261      */
dispatchDestroyView()262     public void dispatchDestroyView() {
263         mHost.mFragmentManager.dispatchDestroyView();
264     }
265 
266     /**
267      * Moves all Fragments managed by the controller's FragmentManager
268      * into the destroy state.
269      * <p>Call when Fragments should be destroyed.
270      *
271      * @see Fragment#onDestroy()
272      */
dispatchDestroy()273     public void dispatchDestroy() {
274         mHost.mFragmentManager.dispatchDestroy();
275     }
276 
277     /**
278      * Lets all Fragments managed by the controller's FragmentManager know the multi-window mode of
279      * the activity changed.
280      * <p>Call when the multi-window mode of the activity changed.
281      *
282      * @see Fragment#onMultiWindowModeChanged
283      */
dispatchMultiWindowModeChanged(boolean isInMultiWindowMode)284     public void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode) {
285         mHost.mFragmentManager.dispatchMultiWindowModeChanged(isInMultiWindowMode);
286     }
287 
288     /**
289      * Lets all Fragments managed by the controller's FragmentManager know the picture-in-picture
290      * mode of the activity changed.
291      * <p>Call when the picture-in-picture mode of the activity changed.
292      *
293      * @see Fragment#onPictureInPictureModeChanged
294      */
dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode)295     public void dispatchPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
296         mHost.mFragmentManager.dispatchPictureInPictureModeChanged(isInPictureInPictureMode);
297     }
298 
299     /**
300      * Lets all Fragments managed by the controller's FragmentManager
301      * know a configuration change occurred.
302      * <p>Call when there is a configuration change.
303      *
304      * @see Fragment#onConfigurationChanged(Configuration)
305      */
dispatchConfigurationChanged(Configuration newConfig)306     public void dispatchConfigurationChanged(Configuration newConfig) {
307         mHost.mFragmentManager.dispatchConfigurationChanged(newConfig);
308     }
309 
310     /**
311      * Lets all Fragments managed by the controller's FragmentManager
312      * know the device is in a low memory condition.
313      * <p>Call when the device is low on memory and Fragment's should trim
314      * their memory usage.
315      *
316      * @see Fragment#onLowMemory()
317      */
dispatchLowMemory()318     public void dispatchLowMemory() {
319         mHost.mFragmentManager.dispatchLowMemory();
320     }
321 
322     /**
323      * Lets all Fragments managed by the controller's FragmentManager
324      * know they should create an options menu.
325      * <p>Call when the Fragment should create an options menu.
326      *
327      * @return {@code true} if the options menu contains items to display
328      * @see Fragment#onCreateOptionsMenu(Menu, MenuInflater)
329      */
dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater)330     public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
331         return mHost.mFragmentManager.dispatchCreateOptionsMenu(menu, inflater);
332     }
333 
334     /**
335      * Lets all Fragments managed by the controller's FragmentManager
336      * know they should prepare their options menu for display.
337      * <p>Call immediately before displaying the Fragment's options menu.
338      *
339      * @return {@code true} if the options menu contains items to display
340      * @see Fragment#onPrepareOptionsMenu(Menu)
341      */
dispatchPrepareOptionsMenu(Menu menu)342     public boolean dispatchPrepareOptionsMenu(Menu menu) {
343         return mHost.mFragmentManager.dispatchPrepareOptionsMenu(menu);
344     }
345 
346     /**
347      * Sends an option item selection event to the Fragments managed by the
348      * controller's FragmentManager. Once the event has been consumed,
349      * no additional handling will be performed.
350      * <p>Call immediately after an options menu item has been selected
351      *
352      * @return {@code true} if the options menu selection event was consumed
353      * @see Fragment#onOptionsItemSelected(MenuItem)
354      */
dispatchOptionsItemSelected(MenuItem item)355     public boolean dispatchOptionsItemSelected(MenuItem item) {
356         return mHost.mFragmentManager.dispatchOptionsItemSelected(item);
357     }
358 
359     /**
360      * Sends a context item selection event to the Fragments managed by the
361      * controller's FragmentManager. Once the event has been consumed,
362      * no additional handling will be performed.
363      * <p>Call immediately after an options menu item has been selected
364      *
365      * @return {@code true} if the context menu selection event was consumed
366      * @see Fragment#onContextItemSelected(MenuItem)
367      */
dispatchContextItemSelected(MenuItem item)368     public boolean dispatchContextItemSelected(MenuItem item) {
369         return mHost.mFragmentManager.dispatchContextItemSelected(item);
370     }
371 
372     /**
373      * Lets all Fragments managed by the controller's FragmentManager
374      * know their options menu has closed.
375      * <p>Call immediately after closing the Fragment's options menu.
376      *
377      * @see Fragment#onOptionsMenuClosed(Menu)
378      */
dispatchOptionsMenuClosed(Menu menu)379     public void dispatchOptionsMenuClosed(Menu menu) {
380         mHost.mFragmentManager.dispatchOptionsMenuClosed(menu);
381     }
382 
383     /**
384      * Execute any pending actions for the Fragments managed by the
385      * controller's FragmentManager.
386      * <p>Call when queued actions can be performed [eg when the
387      * Fragment moves into a start or resume state].
388      * @return {@code true} if queued actions were performed
389      */
execPendingActions()390     public boolean execPendingActions() {
391         return mHost.mFragmentManager.execPendingActions();
392     }
393 
394     /**
395      * Starts the loaders.
396      *
397      * @deprecated Loaders are managed separately from FragmentController
398      */
399     @Deprecated
doLoaderStart()400     public void doLoaderStart() {
401     }
402 
403     /**
404      * Stops the loaders, optionally retaining their state. This is useful for keeping the
405      * loader state across configuration changes.
406      *
407      * @param retain When {@code true}, the loaders aren't stopped, but, their instances
408      * are retained in a started state
409      *
410      * @deprecated Loaders are managed separately from FragmentController
411      */
412     @Deprecated
doLoaderStop(boolean retain)413     public void doLoaderStop(boolean retain) {
414     }
415 
416     /**
417      * Retains the state of each of the loaders.
418      *
419      * @deprecated Loaders are managed separately from FragmentController
420      */
421     @Deprecated
doLoaderRetain()422     public void doLoaderRetain() {
423     }
424 
425     /**
426      * Destroys the loaders and, if their state is not being retained, removes them.
427      *
428      * @deprecated Loaders are managed separately from FragmentController
429      */
430     @Deprecated
doLoaderDestroy()431     public void doLoaderDestroy() {
432     }
433 
434     /**
435      * Lets the loaders know the host is ready to receive notifications.
436      *
437      * @deprecated Loaders are managed separately from FragmentController
438      */
439     @Deprecated
reportLoaderStart()440     public void reportLoaderStart() {
441     }
442 
443     /**
444      * Returns a list of LoaderManagers that have opted to retain their instance across
445      * configuration changes.
446      *
447      * @deprecated Loaders are managed separately from FragmentController
448      */
449     @Deprecated
retainLoaderNonConfig()450     public SimpleArrayMap<String, LoaderManager> retainLoaderNonConfig() {
451         return null;
452     }
453 
454     /**
455      * Restores the saved state for all LoaderManagers. The given LoaderManager list are
456      * LoaderManager instances retained across configuration changes.
457      *
458      * @see #retainLoaderNonConfig()
459      *
460      * @deprecated Loaders are managed separately from FragmentController
461      */
462     @Deprecated
restoreLoaderNonConfig(SimpleArrayMap<String, LoaderManager> loaderManagers)463     public void restoreLoaderNonConfig(SimpleArrayMap<String, LoaderManager> loaderManagers) {
464     }
465 
466     /**
467      * Dumps the current state of the loaders.
468      *
469      * @deprecated Loaders are managed separately from FragmentController
470      */
471     @Deprecated
dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args)472     public void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
473     }
474 }
475