Todd Kennedy | a5fc6f0 | 2015-04-14 18:22:54 -0700 | [diff] [blame] | 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.app; |
| 18 | |
| 19 | import android.annotation.Nullable; |
| 20 | import android.content.Context; |
| 21 | import android.content.res.Configuration; |
| 22 | import android.os.Bundle; |
| 23 | import android.os.Parcelable; |
| 24 | import android.util.ArrayMap; |
| 25 | import android.util.AttributeSet; |
| 26 | import android.view.Menu; |
| 27 | import android.view.MenuInflater; |
| 28 | import android.view.MenuItem; |
| 29 | import android.view.View; |
| 30 | |
| 31 | import java.io.FileDescriptor; |
| 32 | import java.io.PrintWriter; |
| 33 | import 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 | */ |
| 41 | public 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() |
Adam Powell | 7466be6 | 2016-02-04 16:20:37 -0800 | [diff] [blame] | 120 | * |
| 121 | * @deprecated use {@link #restoreAllState(Parcelable, FragmentManagerNonConfig)} |
Todd Kennedy | a5fc6f0 | 2015-04-14 18:22:54 -0700 | [diff] [blame] | 122 | */ |
| 123 | public void restoreAllState(Parcelable state, List<Fragment> nonConfigList) { |
Adam Powell | 7466be6 | 2016-02-04 16:20:37 -0800 | [diff] [blame] | 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); |
Todd Kennedy | a5fc6f0 | 2015-04-14 18:22:54 -0700 | [diff] [blame] | 136 | } |
| 137 | |
| 138 | /** |
| 139 | * Returns a list of Fragments that have opted to retain their instance across |
| 140 | * configuration changes. |
Adam Powell | 7466be6 | 2016-02-04 16:20:37 -0800 | [diff] [blame] | 141 | * |
| 142 | * @deprecated use {@link #retainNestedNonConfig()} to also track retained |
| 143 | * nested child fragments |
Todd Kennedy | a5fc6f0 | 2015-04-14 18:22:54 -0700 | [diff] [blame] | 144 | */ |
| 145 | public List<Fragment> retainNonConfig() { |
Adam Powell | 7466be6 | 2016-02-04 16:20:37 -0800 | [diff] [blame] | 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() { |
Todd Kennedy | a5fc6f0 | 2015-04-14 18:22:54 -0700 | [diff] [blame] | 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 | /** |
Wale Ogunwale | 7c79681 | 2016-01-29 21:13:50 -0800 | [diff] [blame] | 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 | /** |
Todd Kennedy | a5fc6f0 | 2015-04-14 18:22:54 -0700 | [diff] [blame] | 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); |
Todd Kennedy | a5fc6f0 | 2015-04-14 18:22:54 -0700 | [diff] [blame] | 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 | } |