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