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