blob: 063194310e77d89a3a2c149aca149597bfc1839d [file] [log] [blame]
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001/*
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
17package android.app;
18
Chet Haasea18a86b2010-09-07 13:20:00 -070019import android.animation.Animator;
20import android.animation.AnimatorInflater;
Chet Haaseb20db3e2010-09-10 13:07:30 -070021import android.animation.AnimatorListenerAdapter;
Doris Liude9284d2015-05-22 15:41:46 -070022import android.animation.AnimatorSet;
23import android.animation.PropertyValuesHolder;
24import android.animation.ValueAnimator;
Adam Powell371a8092014-06-20 12:51:12 -070025import android.content.Context;
Dianne Hackborn9d071802010-12-08 14:49:15 -080026import android.content.res.Configuration;
Adam Powelle01f5952016-02-23 15:25:42 -080027import android.content.res.Resources.NotFoundException;
Dianne Hackbornf121be72010-05-06 14:10:32 -070028import android.content.res.TypedArray;
Dianne Hackborn2dedce62010-04-15 14:45:25 -070029import android.os.Bundle;
Dianne Hackbornf43a33c2012-09-27 00:48:11 -070030import android.os.Debug;
Dianne Hackbornba51c3d2010-05-05 18:49:48 -070031import android.os.Handler;
Dianne Hackborn3a57fb92010-11-15 17:58:52 -080032import android.os.Looper;
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -070033import android.os.Parcel;
34import android.os.Parcelable;
Adam Powell371a8092014-06-20 12:51:12 -070035import android.util.AttributeSet;
Dianne Hackborna2ea7472010-12-20 12:10:01 -080036import android.util.DebugUtils;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070037import android.util.Log;
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -080038import android.util.LogWriter;
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -070039import android.util.SparseArray;
Adam Powell14874662013-07-18 19:42:41 -070040import android.util.SuperNotCalledException;
Adam Powell371a8092014-06-20 12:51:12 -070041import android.view.LayoutInflater;
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -070042import android.view.Menu;
43import android.view.MenuInflater;
44import android.view.MenuItem;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -070045import android.view.View;
Dianne Hackborn2dedce62010-04-15 14:45:25 -070046import android.view.ViewGroup;
Dianne Hackborn8c841092013-06-24 13:46:13 -070047import com.android.internal.util.FastPrintWriter;
Dianne Hackborn2dedce62010-04-15 14:45:25 -070048
Dianne Hackborn625ac272010-09-17 18:29:22 -070049import java.io.FileDescriptor;
50import java.io.PrintWriter;
Dianne Hackborn2dedce62010-04-15 14:45:25 -070051import java.util.ArrayList;
Dianne Hackbornd173fa32010-12-23 13:58:22 -080052import java.util.Arrays;
Todd Kennedya5fc6f02015-04-14 18:22:54 -070053import java.util.List;
Dianne Hackborn2dedce62010-04-15 14:45:25 -070054
Dianne Hackbornb7a2e472010-08-12 16:20:42 -070055/**
56 * Interface for interacting with {@link Fragment} objects inside of an
57 * {@link Activity}
Joe Fernandezb54e7a32011-10-03 15:09:50 -070058 *
59 * <div class="special reference">
60 * <h3>Developer Guides</h3>
61 * <p>For more information about using fragments, read the
62 * <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
63 * </div>
Dianne Hackborn7871bad2011-12-12 15:19:26 -080064 *
65 * While the FragmentManager API was introduced in
66 * {@link android.os.Build.VERSION_CODES#HONEYCOMB}, a version of the API
67 * at is also available for use on older platforms through
68 * {@link android.support.v4.app.FragmentActivity}. See the blog post
69 * <a href="http://android-developers.blogspot.com/2011/03/fragments-for-all.html">
70 * Fragments For All</a> for more details.
Dianne Hackbornb7a2e472010-08-12 16:20:42 -070071 */
Dianne Hackbornab36acb2010-11-05 14:12:11 -070072public abstract class FragmentManager {
Dianne Hackbornb7a2e472010-08-12 16:20:42 -070073 /**
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070074 * Representation of an entry on the fragment back stack, as created
75 * with {@link FragmentTransaction#addToBackStack(String)
76 * FragmentTransaction.addToBackStack()}. Entries can later be
Dianne Hackborn327fbd22011-01-17 14:38:50 -080077 * retrieved with {@link FragmentManager#getBackStackEntryAt(int)
Mark Dolinerd0646dc2014-08-27 16:04:02 -070078 * FragmentManager.getBackStackEntryAt()}.
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070079 *
80 * <p>Note that you should never hold on to a BackStackEntry object;
81 * the identifier as returned by {@link #getId} is the only thing that
82 * will be persisted across activity instances.
83 */
84 public interface BackStackEntry {
85 /**
86 * Return the unique identifier for the entry. This is the only
87 * representation of the entry that will persist across activity
88 * instances.
89 */
90 public int getId();
91
92 /**
Dianne Hackborn6c285972011-08-29 16:53:49 -070093 * Get the name that was supplied to
94 * {@link FragmentTransaction#addToBackStack(String)
95 * FragmentTransaction.addToBackStack(String)} when creating this entry.
96 */
97 public String getName();
98
99 /**
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800100 * Return the full bread crumb title resource identifier for the entry,
101 * or 0 if it does not have one.
102 */
103 public int getBreadCrumbTitleRes();
104
105 /**
106 * Return the short bread crumb title resource identifier for the entry,
107 * or 0 if it does not have one.
108 */
109 public int getBreadCrumbShortTitleRes();
110
111 /**
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700112 * Return the full bread crumb title for the entry, or null if it
113 * does not have one.
114 */
115 public CharSequence getBreadCrumbTitle();
116
117 /**
118 * Return the short bread crumb title for the entry, or null if it
119 * does not have one.
120 */
121 public CharSequence getBreadCrumbShortTitle();
122 }
123
124 /**
125 * Interface to watch for changes to the back stack.
126 */
127 public interface OnBackStackChangedListener {
128 /**
129 * Called whenever the contents of the back stack change.
130 */
131 public void onBackStackChanged();
132 }
133
134 /**
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700135 * Start a series of edit operations on the Fragments associated with
136 * this FragmentManager.
Dianne Hackbornfb3cffe2010-10-25 17:08:56 -0700137 *
138 * <p>Note: A fragment transaction can only be created/committed prior
139 * to an activity saving its state. If you try to commit a transaction
140 * after {@link Activity#onSaveInstanceState Activity.onSaveInstanceState()}
141 * (and prior to a following {@link Activity#onStart Activity.onStart}
142 * or {@link Activity#onResume Activity.onResume()}, you will get an error.
143 * This is because the framework takes care of saving your current fragments
144 * in the state, and if changes are made after the state is saved then they
145 * will be lost.</p>
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700146 */
Dianne Hackborn48e7b452011-01-17 12:28:35 -0800147 public abstract FragmentTransaction beginTransaction();
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700148
Dianne Hackborn17b9b812011-01-17 17:16:02 -0800149 /** @hide -- remove once prebuilts are in. */
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800150 @Deprecated
Dianne Hackborn48e7b452011-01-17 12:28:35 -0800151 public FragmentTransaction openTransaction() {
152 return beginTransaction();
153 }
154
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700155 /**
Dianne Hackborn3a57fb92010-11-15 17:58:52 -0800156 * After a {@link FragmentTransaction} is committed with
157 * {@link FragmentTransaction#commit FragmentTransaction.commit()}, it
158 * is scheduled to be executed asynchronously on the process's main thread.
159 * If you want to immediately executing any such pending operations, you
160 * can call this function (only from the main thread) to do so. Note that
161 * all callbacks and other related behavior will be done from within this
162 * call, so be careful about where this is called from.
163 *
164 * @return Returns true if there were any pending transactions to be
165 * executed.
166 */
167 public abstract boolean executePendingTransactions();
168
169 /**
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700170 * Finds a fragment that was identified by the given id either when inflated
171 * from XML or as the container ID when added in a transaction. This first
172 * searches through fragments that are currently added to the manager's
173 * activity; if no such fragment is found, then all fragments currently
174 * on the back stack associated with this ID are searched.
175 * @return The fragment if found or null otherwise.
176 */
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700177 public abstract Fragment findFragmentById(int id);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700178
179 /**
180 * Finds a fragment that was identified by the given tag either when inflated
181 * from XML or as supplied when added in a transaction. This first
182 * searches through fragments that are currently added to the manager's
183 * activity; if no such fragment is found, then all fragments currently
184 * on the back stack are searched.
185 * @return The fragment if found or null otherwise.
186 */
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700187 public abstract Fragment findFragmentByTag(String tag);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700188
189 /**
190 * Flag for {@link #popBackStack(String, int)}
191 * and {@link #popBackStack(int, int)}: If set, and the name or ID of
192 * a back stack entry has been supplied, then all matching entries will
193 * be consumed until one that doesn't match is found or the bottom of
194 * the stack is reached. Otherwise, all entries up to but not including that entry
195 * will be removed.
196 */
197 public static final int POP_BACK_STACK_INCLUSIVE = 1<<0;
198
199 /**
Ben Komalo87ffa202011-02-28 12:41:42 -0800200 * Pop the top state off the back stack. This function is asynchronous -- it
201 * enqueues the request to pop, but the action will not be performed until the
202 * application returns to its event loop.
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700203 */
Dianne Hackborn3a57fb92010-11-15 17:58:52 -0800204 public abstract void popBackStack();
205
206 /**
207 * Like {@link #popBackStack()}, but performs the operation immediately
208 * inside of the call. This is like calling {@link #executePendingTransactions()}
209 * afterwards.
210 * @return Returns true if there was something popped, else false.
211 */
212 public abstract boolean popBackStackImmediate();
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700213
214 /**
215 * Pop the last fragment transition from the manager's fragment
216 * back stack. If there is nothing to pop, false is returned.
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800217 * This function is asynchronous -- it enqueues the
218 * request to pop, but the action will not be performed until the application
219 * returns to its event loop.
220 *
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700221 * @param name If non-null, this is the name of a previous back state
222 * to look for; if found, all states up to that state will be popped. The
223 * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether
224 * the named state itself is popped. If null, only the top state is popped.
225 * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
226 */
Dianne Hackborn3a57fb92010-11-15 17:58:52 -0800227 public abstract void popBackStack(String name, int flags);
228
229 /**
230 * Like {@link #popBackStack(String, int)}, but performs the operation immediately
231 * inside of the call. This is like calling {@link #executePendingTransactions()}
232 * afterwards.
233 * @return Returns true if there was something popped, else false.
234 */
235 public abstract boolean popBackStackImmediate(String name, int flags);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700236
237 /**
238 * Pop all back stack states up to the one with the given identifier.
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800239 * This function is asynchronous -- it enqueues the
240 * request to pop, but the action will not be performed until the application
241 * returns to its event loop.
242 *
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700243 * @param id Identifier of the stated to be popped. If no identifier exists,
244 * false is returned.
245 * The identifier is the number returned by
246 * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. The
247 * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether
248 * the named state itself is popped.
249 * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
250 */
Dianne Hackborn3a57fb92010-11-15 17:58:52 -0800251 public abstract void popBackStack(int id, int flags);
252
253 /**
254 * Like {@link #popBackStack(int, int)}, but performs the operation immediately
255 * inside of the call. This is like calling {@link #executePendingTransactions()}
256 * afterwards.
257 * @return Returns true if there was something popped, else false.
258 */
259 public abstract boolean popBackStackImmediate(int id, int flags);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700260
261 /**
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700262 * Return the number of entries currently in the back stack.
263 */
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800264 public abstract int getBackStackEntryCount();
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700265
266 /**
267 * Return the BackStackEntry at index <var>index</var> in the back stack;
Mark Dolinerd0646dc2014-08-27 16:04:02 -0700268 * where the item on the bottom of the stack has index 0.
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700269 */
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800270 public abstract BackStackEntry getBackStackEntryAt(int index);
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700271
272 /**
273 * Add a new listener for changes to the fragment back stack.
274 */
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700275 public abstract void addOnBackStackChangedListener(OnBackStackChangedListener listener);
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700276
277 /**
278 * Remove a listener that was previously added with
279 * {@link #addOnBackStackChangedListener(OnBackStackChangedListener)}.
280 */
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700281 public abstract void removeOnBackStackChangedListener(OnBackStackChangedListener listener);
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700282
283 /**
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700284 * Put a reference to a fragment in a Bundle. This Bundle can be
285 * persisted as saved state, and when later restoring
286 * {@link #getFragment(Bundle, String)} will return the current
287 * instance of the same fragment.
288 *
289 * @param bundle The bundle in which to put the fragment reference.
290 * @param key The name of the entry in the bundle.
291 * @param fragment The Fragment whose reference is to be stored.
292 */
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700293 public abstract void putFragment(Bundle bundle, String key, Fragment fragment);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700294
295 /**
296 * Retrieve the current Fragment instance for a reference previously
297 * placed with {@link #putFragment(Bundle, String, Fragment)}.
298 *
299 * @param bundle The bundle from which to retrieve the fragment reference.
300 * @param key The name of the entry in the bundle.
301 * @return Returns the current Fragment instance that is associated with
302 * the given reference.
303 */
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700304 public abstract Fragment getFragment(Bundle bundle, String key);
Dianne Hackborn625ac272010-09-17 18:29:22 -0700305
306 /**
Dianne Hackbornb46ed762011-06-02 18:33:15 -0700307 * Save the current instance state of the given Fragment. This can be
308 * used later when creating a new instance of the Fragment and adding
309 * it to the fragment manager, to have it create itself to match the
310 * current state returned here. Note that there are limits on how
311 * this can be used:
312 *
313 * <ul>
314 * <li>The Fragment must currently be attached to the FragmentManager.
315 * <li>A new Fragment created using this saved state must be the same class
316 * type as the Fragment it was created from.
317 * <li>The saved state can not contain dependencies on other fragments --
318 * that is it can't use {@link #putFragment(Bundle, String, Fragment)} to
319 * store a fragment reference because that reference may not be valid when
320 * this saved state is later used. Likewise the Fragment's target and
321 * result code are not included in this state.
322 * </ul>
323 *
324 * @param f The Fragment whose state is to be saved.
325 * @return The generated state. This will be null if there was no
326 * interesting state created by the fragment.
327 */
328 public abstract Fragment.SavedState saveFragmentInstanceState(Fragment f);
329
330 /**
Dianne Hackborn6d9dcbc2012-10-02 17:51:13 -0700331 * Returns true if the final {@link Activity#onDestroy() Activity.onDestroy()}
332 * call has been made on the FragmentManager's Activity, so this instance is now dead.
333 */
334 public abstract boolean isDestroyed();
335
336 /**
Dianne Hackborn625ac272010-09-17 18:29:22 -0700337 * Print the FragmentManager's state into the given stream.
338 *
339 * @param prefix Text to print at the front of each line.
340 * @param fd The raw file descriptor that the dump is being sent to.
341 * @param writer A PrintWriter to which the dump is to be set.
Dianne Hackborn30d71892010-12-11 10:37:55 -0800342 * @param args Additional arguments to the dump request.
Dianne Hackborn625ac272010-09-17 18:29:22 -0700343 */
Dianne Hackbornab36acb2010-11-05 14:12:11 -0700344 public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
Dianne Hackborna2ea7472010-12-20 12:10:01 -0800345
346 /**
347 * Control whether the framework's internal fragment manager debugging
348 * logs are turned on. If enabled, you will see output in logcat as
349 * the framework performs fragment operations.
350 */
351 public static void enableDebugLogging(boolean enabled) {
352 FragmentManagerImpl.DEBUG = enabled;
353 }
Adam Powellf0f5fff2011-08-01 13:42:50 -0700354
355 /**
356 * Invalidate the attached activity's options menu as necessary.
357 * This may end up being deferred until we move to the resumed state.
358 */
359 public void invalidateOptionsMenu() { }
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700360}
361
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700362final class FragmentManagerState implements Parcelable {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700363 FragmentState[] mActive;
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700364 int[] mAdded;
365 BackStackState[] mBackStack;
366
367 public FragmentManagerState() {
368 }
369
370 public FragmentManagerState(Parcel in) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700371 mActive = in.createTypedArray(FragmentState.CREATOR);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700372 mAdded = in.createIntArray();
373 mBackStack = in.createTypedArray(BackStackState.CREATOR);
374 }
375
376 public int describeContents() {
377 return 0;
378 }
379
380 public void writeToParcel(Parcel dest, int flags) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700381 dest.writeTypedArray(mActive, flags);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700382 dest.writeIntArray(mAdded);
383 dest.writeTypedArray(mBackStack, flags);
384 }
385
386 public static final Parcelable.Creator<FragmentManagerState> CREATOR
387 = new Parcelable.Creator<FragmentManagerState>() {
388 public FragmentManagerState createFromParcel(Parcel in) {
389 return new FragmentManagerState(in);
390 }
391
392 public FragmentManagerState[] newArray(int size) {
393 return new FragmentManagerState[size];
394 }
395 };
Dianne Hackbornba51c3d2010-05-05 18:49:48 -0700396}
397
Dianne Hackborn2dedce62010-04-15 14:45:25 -0700398/**
399 * Container for fragments associated with an activity.
400 */
Adam Powell371a8092014-06-20 12:51:12 -0700401final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
Craig Mautner1c437192012-08-01 10:01:16 -0700402 static boolean DEBUG = false;
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700403 static final String TAG = "FragmentManager";
404
Dianne Hackborndef15372010-08-15 12:43:52 -0700405 static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state";
406 static final String TARGET_STATE_TAG = "android:target_state";
407 static final String VIEW_STATE_TAG = "android:view_state";
Adam Powell78fed9b2011-11-07 10:45:34 -0800408 static final String USER_VISIBLE_HINT_TAG = "android:user_visible_hint";
Dianne Hackborndef15372010-08-15 12:43:52 -0700409
Doris Liude9284d2015-05-22 15:41:46 -0700410 static class AnimateOnHWLayerIfNeededListener implements Animator.AnimatorListener {
411 private boolean mShouldRunOnHWLayer = false;
412 private View mView;
413 public AnimateOnHWLayerIfNeededListener(final View v) {
414 if (v == null) {
415 return;
416 }
417 mView = v;
418 }
419
420 @Override
421 public void onAnimationStart(Animator animation) {
422 mShouldRunOnHWLayer = shouldRunOnHWLayer(mView, animation);
423 if (mShouldRunOnHWLayer) {
424 mView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
425 }
426 }
427
428 @Override
429 public void onAnimationEnd(Animator animation) {
430 if (mShouldRunOnHWLayer) {
431 mView.setLayerType(View.LAYER_TYPE_NONE, null);
432 }
433 mView = null;
434 animation.removeListener(this);
435 }
436
437 @Override
438 public void onAnimationCancel(Animator animation) {
439
440 }
441
442 @Override
443 public void onAnimationRepeat(Animator animation) {
444
445 }
446 }
447
Dianne Hackborn445646c2010-06-25 15:52:59 -0700448 ArrayList<Runnable> mPendingActions;
449 Runnable[] mTmpActions;
450 boolean mExecutingActions;
451
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700452 ArrayList<Fragment> mActive;
453 ArrayList<Fragment> mAdded;
454 ArrayList<Integer> mAvailIndices;
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700455 ArrayList<BackStackRecord> mBackStack;
Dianne Hackborn8eb2e242010-11-01 12:31:24 -0700456 ArrayList<Fragment> mCreatedMenus;
Dianne Hackborn2dedce62010-04-15 14:45:25 -0700457
Dianne Hackborndd913a52010-07-22 12:17:04 -0700458 // Must be accessed while locked.
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700459 ArrayList<BackStackRecord> mBackStackIndices;
Dianne Hackborndd913a52010-07-22 12:17:04 -0700460 ArrayList<Integer> mAvailBackStackIndices;
461
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700462 ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
463
Dianne Hackborn2dedce62010-04-15 14:45:25 -0700464 int mCurState = Fragment.INITIALIZING;
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700465 FragmentHostCallback<?> mHost;
466 FragmentController mController;
Dianne Hackborn62bea2f2012-09-04 18:48:15 -0700467 FragmentContainer mContainer;
468 Fragment mParent;
Dianne Hackborn2dedce62010-04-15 14:45:25 -0700469
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -0700470 boolean mNeedMenuInvalidate;
Dianne Hackborn3e449ce2010-09-11 20:52:31 -0700471 boolean mStateSaved;
Dianne Hackbornd173fa32010-12-23 13:58:22 -0800472 boolean mDestroyed;
Dianne Hackbornfb3cffe2010-10-25 17:08:56 -0700473 String mNoTransactionsBecause;
Adam Powell78fed9b2011-11-07 10:45:34 -0800474 boolean mHavePendingDeferredStart;
Adam Powell371a8092014-06-20 12:51:12 -0700475
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700476 // Temporary vars for state save and restore.
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700477 Bundle mStateBundle = null;
478 SparseArray<Parcelable> mStateArray = null;
479
Dianne Hackborn445646c2010-06-25 15:52:59 -0700480 Runnable mExecCommit = new Runnable() {
481 @Override
482 public void run() {
483 execPendingActions();
484 }
485 };
Dianne Hackborn625ac272010-09-17 18:29:22 -0700486
Dianne Hackborn4702a852012-08-17 15:18:29 -0700487 private void throwException(RuntimeException ex) {
488 Log.e(TAG, ex.getMessage());
489 LogWriter logw = new LogWriter(Log.ERROR, TAG);
Dianne Hackborn8c841092013-06-24 13:46:13 -0700490 PrintWriter pw = new FastPrintWriter(logw, false, 1024);
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700491 if (mHost != null) {
Dianne Hackborn4702a852012-08-17 15:18:29 -0700492 Log.e(TAG, "Activity state:");
Dianne Hackborn5bf6e1a2012-08-14 18:35:02 -0700493 try {
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700494 mHost.onDump(" ", null, pw, new String[] { });
Dianne Hackborn5bf6e1a2012-08-14 18:35:02 -0700495 } catch (Exception e) {
Dianne Hackborn8c841092013-06-24 13:46:13 -0700496 pw.flush();
Dianne Hackborn5bf6e1a2012-08-14 18:35:02 -0700497 Log.e(TAG, "Failed dumping state", e);
498 }
499 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -0700500 Log.e(TAG, "Fragment manager state:");
Dianne Hackborn5bf6e1a2012-08-14 18:35:02 -0700501 try {
Dianne Hackborn4702a852012-08-17 15:18:29 -0700502 dump(" ", null, pw, new String[] { });
Dianne Hackborn5bf6e1a2012-08-14 18:35:02 -0700503 } catch (Exception e) {
Dianne Hackborn8c841092013-06-24 13:46:13 -0700504 pw.flush();
Dianne Hackborn4702a852012-08-17 15:18:29 -0700505 Log.e(TAG, "Failed dumping state", e);
Dianne Hackborn5bf6e1a2012-08-14 18:35:02 -0700506 }
Dianne Hackborn5bf6e1a2012-08-14 18:35:02 -0700507 }
Dianne Hackborn8c841092013-06-24 13:46:13 -0700508 pw.flush();
Dianne Hackborn4702a852012-08-17 15:18:29 -0700509 throw ex;
Dianne Hackborn5bf6e1a2012-08-14 18:35:02 -0700510 }
511
Doris Liude9284d2015-05-22 15:41:46 -0700512 static boolean modifiesAlpha(Animator anim) {
513 if (anim == null) {
514 return false;
515 }
516 if (anim instanceof ValueAnimator) {
517 ValueAnimator valueAnim = (ValueAnimator) anim;
518 PropertyValuesHolder[] values = valueAnim.getValues();
519 for (int i = 0; i < values.length; i++) {
520 if (("alpha").equals(values[i].getPropertyName())) {
521 return true;
522 }
523 }
524 } else if (anim instanceof AnimatorSet) {
525 List<Animator> animList = ((AnimatorSet) anim).getChildAnimations();
526 for (int i = 0; i < animList.size(); i++) {
527 if (modifiesAlpha(animList.get(i))) {
528 return true;
529 }
530 }
531 }
532 return false;
533 }
534
535 static boolean shouldRunOnHWLayer(View v, Animator anim) {
536 if (v == null || anim == null) {
537 return false;
538 }
539 return v.getLayerType() == View.LAYER_TYPE_NONE
540 && v.hasOverlappingRendering()
541 && modifiesAlpha(anim);
542 }
543
544 /**
545 * Sets the to be animated view on hardware layer during the animation.
546 */
547 private void setHWLayerAnimListenerIfAlpha(final View v, Animator anim) {
548 if (v == null || anim == null) {
549 return;
550 }
551 if (shouldRunOnHWLayer(v, anim)) {
552 anim.addListener(new AnimateOnHWLayerIfNeededListener(v));
553 }
554 }
555
Dianne Hackborn625ac272010-09-17 18:29:22 -0700556 @Override
Dianne Hackborn48e7b452011-01-17 12:28:35 -0800557 public FragmentTransaction beginTransaction() {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700558 return new BackStackRecord(this);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700559 }
560
Dianne Hackborn625ac272010-09-17 18:29:22 -0700561 @Override
Dianne Hackborn3a57fb92010-11-15 17:58:52 -0800562 public boolean executePendingTransactions() {
563 return execPendingActions();
564 }
565
566 @Override
567 public void popBackStack() {
568 enqueueAction(new Runnable() {
569 @Override public void run() {
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700570 popBackStackState(mHost.getHandler(), null, -1, 0);
Dianne Hackborn3a57fb92010-11-15 17:58:52 -0800571 }
572 }, false);
573 }
574
575 @Override
576 public boolean popBackStackImmediate() {
577 checkStateLoss();
578 executePendingTransactions();
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700579 return popBackStackState(mHost.getHandler(), null, -1, 0);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700580 }
581
Dianne Hackborn625ac272010-09-17 18:29:22 -0700582 @Override
Dianne Hackborn3a57fb92010-11-15 17:58:52 -0800583 public void popBackStack(final String name, final int flags) {
584 enqueueAction(new Runnable() {
585 @Override public void run() {
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700586 popBackStackState(mHost.getHandler(), name, -1, flags);
Dianne Hackborn3a57fb92010-11-15 17:58:52 -0800587 }
588 }, false);
589 }
590
591 @Override
592 public boolean popBackStackImmediate(String name, int flags) {
593 checkStateLoss();
594 executePendingTransactions();
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700595 return popBackStackState(mHost.getHandler(), name, -1, flags);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700596 }
597
Dianne Hackborn625ac272010-09-17 18:29:22 -0700598 @Override
Dianne Hackborn3a57fb92010-11-15 17:58:52 -0800599 public void popBackStack(final int id, final int flags) {
600 if (id < 0) {
601 throw new IllegalArgumentException("Bad id: " + id);
602 }
603 enqueueAction(new Runnable() {
604 @Override public void run() {
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700605 popBackStackState(mHost.getHandler(), null, id, flags);
Dianne Hackborn3a57fb92010-11-15 17:58:52 -0800606 }
607 }, false);
608 }
609
610 @Override
611 public boolean popBackStackImmediate(int id, int flags) {
612 checkStateLoss();
613 executePendingTransactions();
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700614 if (id < 0) {
615 throw new IllegalArgumentException("Bad id: " + id);
616 }
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700617 return popBackStackState(mHost.getHandler(), null, id, flags);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700618 }
619
Dianne Hackborn625ac272010-09-17 18:29:22 -0700620 @Override
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800621 public int getBackStackEntryCount() {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700622 return mBackStack != null ? mBackStack.size() : 0;
623 }
624
Dianne Hackborn625ac272010-09-17 18:29:22 -0700625 @Override
Dianne Hackborn327fbd22011-01-17 14:38:50 -0800626 public BackStackEntry getBackStackEntryAt(int index) {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700627 return mBackStack.get(index);
628 }
629
Dianne Hackborn625ac272010-09-17 18:29:22 -0700630 @Override
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700631 public void addOnBackStackChangedListener(OnBackStackChangedListener listener) {
632 if (mBackStackChangeListeners == null) {
633 mBackStackChangeListeners = new ArrayList<OnBackStackChangedListener>();
634 }
635 mBackStackChangeListeners.add(listener);
636 }
637
Dianne Hackborn625ac272010-09-17 18:29:22 -0700638 @Override
Dianne Hackbornc6669ca2010-09-16 01:33:24 -0700639 public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) {
640 if (mBackStackChangeListeners != null) {
641 mBackStackChangeListeners.remove(listener);
642 }
643 }
644
Dianne Hackborn625ac272010-09-17 18:29:22 -0700645 @Override
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700646 public void putFragment(Bundle bundle, String key, Fragment fragment) {
647 if (fragment.mIndex < 0) {
Dianne Hackborn4702a852012-08-17 15:18:29 -0700648 throwException(new IllegalStateException("Fragment " + fragment
649 + " is not currently in the FragmentManager"));
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700650 }
651 bundle.putInt(key, fragment.mIndex);
652 }
653
Dianne Hackborn625ac272010-09-17 18:29:22 -0700654 @Override
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700655 public Fragment getFragment(Bundle bundle, String key) {
Dianne Hackborndef15372010-08-15 12:43:52 -0700656 int index = bundle.getInt(key, -1);
657 if (index == -1) {
658 return null;
659 }
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700660 if (index >= mActive.size()) {
Cyril Mottier2de50822013-09-30 22:42:26 +0200661 throwException(new IllegalStateException("Fragment no longer exists for key "
Dianne Hackborn4702a852012-08-17 15:18:29 -0700662 + key + ": index " + index));
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700663 }
664 Fragment f = mActive.get(index);
665 if (f == null) {
Cyril Mottier2de50822013-09-30 22:42:26 +0200666 throwException(new IllegalStateException("Fragment no longer exists for key "
Dianne Hackborn4702a852012-08-17 15:18:29 -0700667 + key + ": index " + index));
Dianne Hackbornb7a2e472010-08-12 16:20:42 -0700668 }
669 return f;
670 }
671
Dianne Hackborn625ac272010-09-17 18:29:22 -0700672 @Override
Dianne Hackbornb46ed762011-06-02 18:33:15 -0700673 public Fragment.SavedState saveFragmentInstanceState(Fragment fragment) {
674 if (fragment.mIndex < 0) {
Dianne Hackborn4702a852012-08-17 15:18:29 -0700675 throwException(new IllegalStateException("Fragment " + fragment
676 + " is not currently in the FragmentManager"));
Dianne Hackbornb46ed762011-06-02 18:33:15 -0700677 }
678 if (fragment.mState > Fragment.INITIALIZING) {
679 Bundle result = saveFragmentBasicState(fragment);
680 return result != null ? new Fragment.SavedState(result) : null;
681 }
682 return null;
683 }
684
685 @Override
Dianne Hackborn6d9dcbc2012-10-02 17:51:13 -0700686 public boolean isDestroyed() {
687 return mDestroyed;
688 }
689
690 @Override
Dianne Hackborna2ea7472010-12-20 12:10:01 -0800691 public String toString() {
692 StringBuilder sb = new StringBuilder(128);
693 sb.append("FragmentManager{");
694 sb.append(Integer.toHexString(System.identityHashCode(this)));
695 sb.append(" in ");
Dianne Hackborn62bea2f2012-09-04 18:48:15 -0700696 if (mParent != null) {
697 DebugUtils.buildShortClassTag(mParent, sb);
698 } else {
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700699 DebugUtils.buildShortClassTag(mHost, sb);
Dianne Hackborn62bea2f2012-09-04 18:48:15 -0700700 }
Dianne Hackborna2ea7472010-12-20 12:10:01 -0800701 sb.append("}}");
702 return sb.toString();
703 }
704
705 @Override
Dianne Hackborn625ac272010-09-17 18:29:22 -0700706 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
Dianne Hackborn625ac272010-09-17 18:29:22 -0700707 String innerPrefix = prefix + " ";
708
Dianne Hackbornd173fa32010-12-23 13:58:22 -0800709 int N;
710 if (mActive != null) {
711 N = mActive.size();
712 if (N > 0) {
713 writer.print(prefix); writer.print("Active Fragments in ");
714 writer.print(Integer.toHexString(System.identityHashCode(this)));
715 writer.println(":");
716 for (int i=0; i<N; i++) {
717 Fragment f = mActive.get(i);
718 writer.print(prefix); writer.print(" #"); writer.print(i);
719 writer.print(": "); writer.println(f);
720 if (f != null) {
721 f.dump(innerPrefix, fd, writer, args);
722 }
723 }
Dianne Hackborn625ac272010-09-17 18:29:22 -0700724 }
725 }
726
727 if (mAdded != null) {
728 N = mAdded.size();
729 if (N > 0) {
730 writer.print(prefix); writer.println("Added Fragments:");
731 for (int i=0; i<N; i++) {
732 Fragment f = mAdded.get(i);
733 writer.print(prefix); writer.print(" #"); writer.print(i);
734 writer.print(": "); writer.println(f.toString());
735 }
736 }
737 }
738
Dianne Hackbornd173fa32010-12-23 13:58:22 -0800739 if (mCreatedMenus != null) {
740 N = mCreatedMenus.size();
741 if (N > 0) {
742 writer.print(prefix); writer.println("Fragments Created Menus:");
743 for (int i=0; i<N; i++) {
744 Fragment f = mCreatedMenus.get(i);
745 writer.print(prefix); writer.print(" #"); writer.print(i);
746 writer.print(": "); writer.println(f.toString());
747 }
748 }
749 }
750
Dianne Hackborn625ac272010-09-17 18:29:22 -0700751 if (mBackStack != null) {
752 N = mBackStack.size();
753 if (N > 0) {
754 writer.print(prefix); writer.println("Back Stack:");
755 for (int i=0; i<N; i++) {
756 BackStackRecord bs = mBackStack.get(i);
757 writer.print(prefix); writer.print(" #"); writer.print(i);
758 writer.print(": "); writer.println(bs.toString());
Dianne Hackborn30d71892010-12-11 10:37:55 -0800759 bs.dump(innerPrefix, fd, writer, args);
Dianne Hackborn625ac272010-09-17 18:29:22 -0700760 }
761 }
762 }
Dianne Hackbornd173fa32010-12-23 13:58:22 -0800763
764 synchronized (this) {
765 if (mBackStackIndices != null) {
766 N = mBackStackIndices.size();
767 if (N > 0) {
768 writer.print(prefix); writer.println("Back Stack Indices:");
769 for (int i=0; i<N; i++) {
770 BackStackRecord bs = mBackStackIndices.get(i);
771 writer.print(prefix); writer.print(" #"); writer.print(i);
772 writer.print(": "); writer.println(bs);
773 }
774 }
775 }
776
777 if (mAvailBackStackIndices != null && mAvailBackStackIndices.size() > 0) {
778 writer.print(prefix); writer.print("mAvailBackStackIndices: ");
779 writer.println(Arrays.toString(mAvailBackStackIndices.toArray()));
780 }
781 }
782
783 if (mPendingActions != null) {
784 N = mPendingActions.size();
785 if (N > 0) {
786 writer.print(prefix); writer.println("Pending Actions:");
787 for (int i=0; i<N; i++) {
788 Runnable r = mPendingActions.get(i);
789 writer.print(prefix); writer.print(" #"); writer.print(i);
790 writer.print(": "); writer.println(r);
791 }
792 }
793 }
794
795 writer.print(prefix); writer.println("FragmentManager misc state:");
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700796 writer.print(prefix); writer.print(" mHost="); writer.println(mHost);
Dianne Hackborn62bea2f2012-09-04 18:48:15 -0700797 writer.print(prefix); writer.print(" mContainer="); writer.println(mContainer);
798 if (mParent != null) {
799 writer.print(prefix); writer.print(" mParent="); writer.println(mParent);
800 }
Dianne Hackbornd173fa32010-12-23 13:58:22 -0800801 writer.print(prefix); writer.print(" mCurState="); writer.print(mCurState);
802 writer.print(" mStateSaved="); writer.print(mStateSaved);
803 writer.print(" mDestroyed="); writer.println(mDestroyed);
804 if (mNeedMenuInvalidate) {
805 writer.print(prefix); writer.print(" mNeedMenuInvalidate=");
806 writer.println(mNeedMenuInvalidate);
807 }
808 if (mNoTransactionsBecause != null) {
809 writer.print(prefix); writer.print(" mNoTransactionsBecause=");
810 writer.println(mNoTransactionsBecause);
811 }
812 if (mAvailIndices != null && mAvailIndices.size() > 0) {
813 writer.print(prefix); writer.print(" mAvailIndices: ");
814 writer.println(Arrays.toString(mAvailIndices.toArray()));
815 }
Dianne Hackborn625ac272010-09-17 18:29:22 -0700816 }
817
Chet Haasea18a86b2010-09-07 13:20:00 -0700818 Animator loadAnimator(Fragment fragment, int transit, boolean enter,
Dianne Hackbornf121be72010-05-06 14:10:32 -0700819 int transitionStyle) {
Chet Haasea18a86b2010-09-07 13:20:00 -0700820 Animator animObj = fragment.onCreateAnimator(transit, enter,
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700821 fragment.mNextAnim);
Dianne Hackbornf121be72010-05-06 14:10:32 -0700822 if (animObj != null) {
823 return animObj;
824 }
825
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700826 if (fragment.mNextAnim != 0) {
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700827 Animator anim = AnimatorInflater.loadAnimator(mHost.getContext(), fragment.mNextAnim);
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700828 if (anim != null) {
829 return anim;
830 }
831 }
832
Dianne Hackbornf121be72010-05-06 14:10:32 -0700833 if (transit == 0) {
834 return null;
835 }
836
837 int styleIndex = transitToStyleIndex(transit, enter);
838 if (styleIndex < 0) {
839 return null;
840 }
841
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700842 if (transitionStyle == 0 && mHost.onHasWindowAnimations()) {
843 transitionStyle = mHost.onGetWindowAnimations();
Dianne Hackbornf121be72010-05-06 14:10:32 -0700844 }
845 if (transitionStyle == 0) {
846 return null;
847 }
848
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700849 TypedArray attrs = mHost.getContext().obtainStyledAttributes(transitionStyle,
Chet Haase811ed1062010-08-06 10:38:15 -0700850 com.android.internal.R.styleable.FragmentAnimation);
Dianne Hackbornf121be72010-05-06 14:10:32 -0700851 int anim = attrs.getResourceId(styleIndex, 0);
852 attrs.recycle();
853
854 if (anim == 0) {
855 return null;
856 }
857
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700858 return AnimatorInflater.loadAnimator(mHost.getContext(), anim);
Dianne Hackbornf121be72010-05-06 14:10:32 -0700859 }
860
Adam Powell635c60a2011-10-26 10:22:16 -0700861 public void performPendingDeferredStart(Fragment f) {
862 if (f.mDeferStart) {
Adam Powell78fed9b2011-11-07 10:45:34 -0800863 if (mExecutingActions) {
864 // Wait until we're done executing our pending transactions
865 mHavePendingDeferredStart = true;
866 return;
867 }
Adam Powell635c60a2011-10-26 10:22:16 -0700868 f.mDeferStart = false;
Dianne Hackbornee76efb2012-06-05 10:27:40 -0700869 moveToState(f, mCurState, 0, 0, false);
Adam Powell635c60a2011-10-26 10:22:16 -0700870 }
871 }
872
Dianne Hackbornee76efb2012-06-05 10:27:40 -0700873 void moveToState(Fragment f, int newState, int transit, int transitionStyle,
874 boolean keepActive) {
Dianne Hackbornf43a33c2012-09-27 00:48:11 -0700875 if (DEBUG && false) Log.v(TAG, "moveToState: " + f
876 + " oldState=" + f.mState + " newState=" + newState
877 + " mRemoving=" + f.mRemoving + " Callers=" + Debug.getCallers(5));
Craig Mautner1c437192012-08-01 10:01:16 -0700878
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700879 // Fragments that are not currently added will sit in the onCreate() state.
Dianne Hackborne181bd92012-09-25 14:15:15 -0700880 if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700881 newState = Fragment.CREATED;
882 }
Dianne Hackbornf9302322011-06-14 18:36:14 -0700883 if (f.mRemoving && newState > f.mState) {
884 // While removing a fragment, we can't change it to a higher state.
885 newState = f.mState;
886 }
Adam Powell2db4e4b2011-11-02 14:30:47 -0700887 // Defer start if requested; don't allow it to move to STARTED or higher
888 // if it's not already started.
889 if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {
Adam Powell635c60a2011-10-26 10:22:16 -0700890 newState = Fragment.STOPPED;
891 }
Dianne Hackborn2dedce62010-04-15 14:45:25 -0700892 if (f.mState < newState) {
Dianne Hackborne3a7f622011-03-03 21:48:24 -0800893 // For fragments that are created from a layout, when restoring from
894 // state we don't want to allow them to be created until they are
895 // being reloaded from the layout.
896 if (f.mFromLayout && !f.mInLayout) {
897 return;
898 }
Dianne Hackbornd173fa32010-12-23 13:58:22 -0800899 if (f.mAnimatingAway != null) {
900 // The fragment is currently being animated... but! Now we
901 // want to move our state back up. Give up on waiting for the
902 // animation, move to whatever the final state should be once
903 // the animation is done, and then we can proceed from there.
904 f.mAnimatingAway = null;
Dianne Hackbornee76efb2012-06-05 10:27:40 -0700905 moveToState(f, f.mStateAfterAnimating, 0, 0, true);
Dianne Hackbornd173fa32010-12-23 13:58:22 -0800906 }
Dianne Hackborn2dedce62010-04-15 14:45:25 -0700907 switch (f.mState) {
908 case Fragment.INITIALIZING:
Dianne Hackborn5ae74d62010-05-19 19:14:57 -0700909 if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
Dianne Hackborndef15372010-08-15 12:43:52 -0700910 if (f.mSavedFragmentState != null) {
911 f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
912 FragmentManagerImpl.VIEW_STATE_TAG);
913 f.mTarget = getFragment(f.mSavedFragmentState,
914 FragmentManagerImpl.TARGET_STATE_TAG);
915 if (f.mTarget != null) {
916 f.mTargetRequestCode = f.mSavedFragmentState.getInt(
917 FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
918 }
Adam Powell78fed9b2011-11-07 10:45:34 -0800919 f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
920 FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
921 if (!f.mUserVisibleHint) {
922 f.mDeferStart = true;
923 if (newState > Fragment.STOPPED) {
924 newState = Fragment.STOPPED;
925 }
926 }
Dianne Hackborndef15372010-08-15 12:43:52 -0700927 }
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700928 f.mHost = mHost;
Dianne Hackborn62bea2f2012-09-04 18:48:15 -0700929 f.mParentFragment = mParent;
930 f.mFragmentManager = mParent != null
Todd Kennedya5fc6f02015-04-14 18:22:54 -0700931 ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
Dianne Hackborn2dedce62010-04-15 14:45:25 -0700932 f.mCalled = false;
Todd Kennedy434bd652015-05-04 12:29:50 -0700933 f.onAttach(mHost.getContext());
Dianne Hackborn2dedce62010-04-15 14:45:25 -0700934 if (!f.mCalled) {
935 throw new SuperNotCalledException("Fragment " + f
936 + " did not call through to super.onAttach()");
937 }
Dianne Hackborn1b8ecc52012-09-08 17:03:52 -0700938 if (f.mParentFragment == null) {
Todd Kennedy434bd652015-05-04 12:29:50 -0700939 mHost.onAttachFragment(f);
Dianne Hackborn1b8ecc52012-09-08 17:03:52 -0700940 }
Dianne Hackborn62bea2f2012-09-04 18:48:15 -0700941
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700942 if (!f.mRetaining) {
Dianne Hackborn62bea2f2012-09-04 18:48:15 -0700943 f.performCreate(f.mSavedFragmentState);
Dianne Hackborn2dedce62010-04-15 14:45:25 -0700944 }
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700945 f.mRetaining = false;
946 if (f.mFromLayout) {
947 // For fragments that are part of the content view
948 // layout, we need to instantiate the view immediately
949 // and the inflater will take care of adding it.
Dianne Hackborn1b8ecc52012-09-08 17:03:52 -0700950 f.mView = f.performCreateView(f.getLayoutInflater(
951 f.mSavedFragmentState), null, f.mSavedFragmentState);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700952 if (f.mView != null) {
953 f.mView.setSaveFromParentEnabled(false);
Dianne Hackborn16f6e892011-04-15 19:00:20 -0700954 if (f.mHidden) f.mView.setVisibility(View.GONE);
Dianne Hackborn16f6e892011-04-15 19:00:20 -0700955 f.onViewCreated(f.mView, f.mSavedFragmentState);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700956 }
Dianne Hackborn2dedce62010-04-15 14:45:25 -0700957 }
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700958 case Fragment.CREATED:
959 if (newState > Fragment.CREATED) {
Dianne Hackborn16f6e892011-04-15 19:00:20 -0700960 if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700961 if (!f.mFromLayout) {
962 ViewGroup container = null;
963 if (f.mContainerId != 0) {
Adam Powelle01f5952016-02-23 15:25:42 -0800964 if (f.mContainerId == View.NO_ID) {
965 throwException(new IllegalArgumentException(
966 "Cannot create fragment "
967 + f
968 + " for a container view with no id"));
969 }
970 container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
Dianne Hackborn352cc982011-01-04 11:34:18 -0800971 if (container == null && !f.mRestored) {
Adam Powelle01f5952016-02-23 15:25:42 -0800972 String resName;
973 try {
974 resName = f.getResources().getResourceName(f.mContainerId);
975 } catch (NotFoundException e) {
976 resName = "unknown";
977 }
Dianne Hackborn4702a852012-08-17 15:18:29 -0700978 throwException(new IllegalArgumentException(
979 "No view found for id 0x"
980 + Integer.toHexString(f.mContainerId) + " ("
Adam Powelle01f5952016-02-23 15:25:42 -0800981 + resName
Dianne Hackborn4702a852012-08-17 15:18:29 -0700982 + ") for fragment " + f));
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700983 }
984 }
985 f.mContainer = container;
Dianne Hackborn1b8ecc52012-09-08 17:03:52 -0700986 f.mView = f.performCreateView(f.getLayoutInflater(
987 f.mSavedFragmentState), container, f.mSavedFragmentState);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700988 if (f.mView != null) {
989 f.mView.setSaveFromParentEnabled(false);
990 if (container != null) {
Chet Haasea18a86b2010-09-07 13:20:00 -0700991 Animator anim = loadAnimator(f, transit, true,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700992 transitionStyle);
993 if (anim != null) {
Chet Haaseb20db3e2010-09-10 13:07:30 -0700994 anim.setTarget(f.mView);
Doris Liude9284d2015-05-22 15:41:46 -0700995 setHWLayerAnimListenerIfAlpha(f.mView, anim);
Chet Haase811ed1062010-08-06 10:38:15 -0700996 anim.start();
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700997 }
998 container.addView(f.mView);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700999 }
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001000 if (f.mHidden) f.mView.setVisibility(View.GONE);
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001001 f.onViewCreated(f.mView, f.mSavedFragmentState);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001002 }
1003 }
Dianne Hackborn1b8ecc52012-09-08 17:03:52 -07001004
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001005 f.performActivityCreated(f.mSavedFragmentState);
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001006 if (f.mView != null) {
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001007 f.restoreViewState(f.mSavedFragmentState);
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001008 }
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001009 f.mSavedFragmentState = null;
1010 }
Dianne Hackbornc8017682010-07-06 13:34:38 -07001011 case Fragment.ACTIVITY_CREATED:
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001012 case Fragment.STOPPED:
1013 if (newState > Fragment.STOPPED) {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001014 if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
Dianne Hackbornafc4b282011-06-10 17:03:42 -07001015 f.performStart();
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001016 }
1017 case Fragment.STARTED:
1018 if (newState > Fragment.STARTED) {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001019 if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001020 f.performResume();
Adam Powell95202512011-08-07 17:20:17 -07001021 // Get rid of this in case we saved it and never needed it.
1022 f.mSavedFragmentState = null;
1023 f.mSavedViewState = null;
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001024 }
1025 }
1026 } else if (f.mState > newState) {
1027 switch (f.mState) {
1028 case Fragment.RESUMED:
1029 if (newState < Fragment.RESUMED) {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001030 if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001031 f.performPause();
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001032 }
1033 case Fragment.STARTED:
1034 if (newState < Fragment.STARTED) {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001035 if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
Dianne Hackborn2707d602010-07-09 18:01:20 -07001036 f.performStop();
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001037 }
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001038 case Fragment.STOPPED:
Dianne Hackbornc8017682010-07-06 13:34:38 -07001039 case Fragment.ACTIVITY_CREATED:
1040 if (newState < Fragment.ACTIVITY_CREATED) {
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001041 if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001042 if (f.mView != null) {
1043 // Need to save the current view state if not
1044 // done already.
Todd Kennedy46d168f2015-05-13 11:13:58 -07001045 if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001046 saveFragmentViewState(f);
Dianne Hackbornf121be72010-05-06 14:10:32 -07001047 }
Dianne Hackborndef15372010-08-15 12:43:52 -07001048 }
Dianne Hackbornafc4b282011-06-10 17:03:42 -07001049 f.performDestroyView();
Dianne Hackborndef15372010-08-15 12:43:52 -07001050 if (f.mView != null && f.mContainer != null) {
Chet Haaseb20db3e2010-09-10 13:07:30 -07001051 Animator anim = null;
Dianne Hackbornd173fa32010-12-23 13:58:22 -08001052 if (mCurState > Fragment.INITIALIZING && !mDestroyed) {
Chet Haaseb20db3e2010-09-10 13:07:30 -07001053 anim = loadAnimator(f, transit, false,
Dianne Hackborndef15372010-08-15 12:43:52 -07001054 transitionStyle);
Chet Haaseb20db3e2010-09-10 13:07:30 -07001055 }
1056 if (anim != null) {
1057 final ViewGroup container = f.mContainer;
1058 final View view = f.mView;
Dianne Hackbornd173fa32010-12-23 13:58:22 -08001059 final Fragment fragment = f;
Chet Haaseb20db3e2010-09-10 13:07:30 -07001060 container.startViewTransition(view);
Dianne Hackbornd173fa32010-12-23 13:58:22 -08001061 f.mAnimatingAway = anim;
1062 f.mStateAfterAnimating = newState;
Chet Haaseb20db3e2010-09-10 13:07:30 -07001063 anim.addListener(new AnimatorListenerAdapter() {
1064 @Override
1065 public void onAnimationEnd(Animator anim) {
1066 container.endViewTransition(view);
Dianne Hackbornd173fa32010-12-23 13:58:22 -08001067 if (fragment.mAnimatingAway != null) {
1068 fragment.mAnimatingAway = null;
1069 moveToState(fragment, fragment.mStateAfterAnimating,
Dianne Hackbornee76efb2012-06-05 10:27:40 -07001070 0, 0, false);
Dianne Hackbornd173fa32010-12-23 13:58:22 -08001071 }
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001072 }
Chet Haaseb20db3e2010-09-10 13:07:30 -07001073 });
1074 anim.setTarget(f.mView);
Doris Liude9284d2015-05-22 15:41:46 -07001075 setHWLayerAnimListenerIfAlpha(f.mView, anim);
Chet Haaseb20db3e2010-09-10 13:07:30 -07001076 anim.start();
1077
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001078 }
Dianne Hackborndef15372010-08-15 12:43:52 -07001079 f.mContainer.removeView(f.mView);
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001080 }
1081 f.mContainer = null;
1082 f.mView = null;
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001083 }
1084 case Fragment.CREATED:
1085 if (newState < Fragment.CREATED) {
Dianne Hackbornd173fa32010-12-23 13:58:22 -08001086 if (mDestroyed) {
1087 if (f.mAnimatingAway != null) {
1088 // The fragment's containing activity is
1089 // being destroyed, but this fragment is
1090 // currently animating away. Stop the
1091 // animation right now -- it is not needed,
1092 // and we can't wait any more on destroying
1093 // the fragment.
Dianne Hackborn1b39e222010-12-28 14:17:18 -08001094 Animator anim = f.mAnimatingAway;
Dianne Hackbornd173fa32010-12-23 13:58:22 -08001095 f.mAnimatingAway = null;
Dianne Hackborn1b39e222010-12-28 14:17:18 -08001096 anim.cancel();
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001097 }
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001098 }
Dianne Hackbornd173fa32010-12-23 13:58:22 -08001099 if (f.mAnimatingAway != null) {
1100 // We are waiting for the fragment's view to finish
1101 // animating away. Just make a note of the state
1102 // the fragment now should move to once the animation
1103 // is done.
1104 f.mStateAfterAnimating = newState;
Dianne Hackbornf9302322011-06-14 18:36:14 -07001105 newState = Fragment.CREATED;
Dianne Hackbornd173fa32010-12-23 13:58:22 -08001106 } else {
1107 if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
1108 if (!f.mRetaining) {
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001109 f.performDestroy();
Adam Powelld1d4d9c2016-01-12 10:11:42 -08001110 } else {
1111 f.mState = Fragment.INITIALIZING;
Dianne Hackbornd173fa32010-12-23 13:58:22 -08001112 }
1113
1114 f.mCalled = false;
1115 f.onDetach();
1116 if (!f.mCalled) {
1117 throw new SuperNotCalledException("Fragment " + f
1118 + " did not call through to super.onDetach()");
1119 }
Dianne Hackbornee76efb2012-06-05 10:27:40 -07001120 if (!keepActive) {
1121 if (!f.mRetaining) {
1122 makeInactive(f);
1123 } else {
Todd Kennedya5fc6f02015-04-14 18:22:54 -07001124 f.mHost = null;
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001125 f.mParentFragment = null;
Dianne Hackbornee76efb2012-06-05 10:27:40 -07001126 f.mFragmentManager = null;
Tim Kilbourn70717862014-02-28 01:00:06 -08001127 f.mChildFragmentManager = null;
Dianne Hackbornee76efb2012-06-05 10:27:40 -07001128 }
Dianne Hackbornf9302322011-06-14 18:36:14 -07001129 }
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001130 }
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001131 }
1132 }
1133 }
1134
Adam Powelld1d4d9c2016-01-12 10:11:42 -08001135 if (f.mState != newState) {
1136 Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
1137 + "expected state " + newState + " found " + f.mState);
1138 f.mState = newState;
1139 }
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001140 }
1141
Dianne Hackborn625ac272010-09-17 18:29:22 -07001142 void moveToState(Fragment f) {
Dianne Hackbornee76efb2012-06-05 10:27:40 -07001143 moveToState(f, mCurState, 0, 0, false);
Dianne Hackborn625ac272010-09-17 18:29:22 -07001144 }
1145
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001146 void moveToState(int newState, boolean always) {
Dianne Hackbornf121be72010-05-06 14:10:32 -07001147 moveToState(newState, 0, 0, always);
1148 }
1149
1150 void moveToState(int newState, int transit, int transitStyle, boolean always) {
Todd Kennedya5fc6f02015-04-14 18:22:54 -07001151 if (mHost == null && newState != Fragment.INITIALIZING) {
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001152 throw new IllegalStateException("No activity");
1153 }
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001154
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001155 if (!always && mCurState == newState) {
1156 return;
1157 }
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001158
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001159 mCurState = newState;
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001160 if (mActive != null) {
Adam Powell635c60a2011-10-26 10:22:16 -07001161 boolean loadersRunning = false;
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001162 for (int i=0; i<mActive.size(); i++) {
1163 Fragment f = mActive.get(i);
1164 if (f != null) {
Dianne Hackbornee76efb2012-06-05 10:27:40 -07001165 moveToState(f, newState, transit, transitStyle, false);
Adam Powell635c60a2011-10-26 10:22:16 -07001166 if (f.mLoaderManager != null) {
1167 loadersRunning |= f.mLoaderManager.hasRunningLoaders();
1168 }
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001169 }
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001170 }
Dianne Hackborn5f36c962010-08-26 15:54:17 -07001171
Adam Powell635c60a2011-10-26 10:22:16 -07001172 if (!loadersRunning) {
1173 startPendingDeferredFragments();
1174 }
1175
Todd Kennedya5fc6f02015-04-14 18:22:54 -07001176 if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
1177 mHost.onInvalidateOptionsMenu();
Dianne Hackborn5f36c962010-08-26 15:54:17 -07001178 mNeedMenuInvalidate = false;
1179 }
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001180 }
1181 }
1182
Adam Powell635c60a2011-10-26 10:22:16 -07001183 void startPendingDeferredFragments() {
Adam Powell37510902011-10-31 11:48:24 -07001184 if (mActive == null) return;
1185
Adam Powell635c60a2011-10-26 10:22:16 -07001186 for (int i=0; i<mActive.size(); i++) {
1187 Fragment f = mActive.get(i);
1188 if (f != null) {
1189 performPendingDeferredStart(f);
1190 }
1191 }
1192 }
1193
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001194 void makeActive(Fragment f) {
1195 if (f.mIndex >= 0) {
1196 return;
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001197 }
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001198
1199 if (mAvailIndices == null || mAvailIndices.size() <= 0) {
1200 if (mActive == null) {
1201 mActive = new ArrayList<Fragment>();
1202 }
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001203 f.setIndex(mActive.size(), mParent);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001204 mActive.add(f);
1205
1206 } else {
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001207 f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1), mParent);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001208 mActive.set(f.mIndex, f);
1209 }
Dianne Hackborn03fcc332012-05-15 12:49:40 -07001210 if (DEBUG) Log.v(TAG, "Allocated fragment index " + f);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001211 }
1212
1213 void makeInactive(Fragment f) {
1214 if (f.mIndex < 0) {
1215 return;
1216 }
1217
Dianne Hackborn03fcc332012-05-15 12:49:40 -07001218 if (DEBUG) Log.v(TAG, "Freeing fragment index " + f);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001219 mActive.set(f.mIndex, null);
1220 if (mAvailIndices == null) {
1221 mAvailIndices = new ArrayList<Integer>();
1222 }
1223 mAvailIndices.add(f.mIndex);
Todd Kennedya5fc6f02015-04-14 18:22:54 -07001224 mHost.inactivateFragment(f.mWho);
Dianne Hackbornafc4b282011-06-10 17:03:42 -07001225 f.initState();
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001226 }
1227
1228 public void addFragment(Fragment fragment, boolean moveToStateNow) {
1229 if (mAdded == null) {
1230 mAdded = new ArrayList<Fragment>();
1231 }
Dianne Hackborn5e0d5952010-08-05 13:45:35 -07001232 if (DEBUG) Log.v(TAG, "add: " + fragment);
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001233 makeActive(fragment);
1234 if (!fragment.mDetached) {
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07001235 if (mAdded.contains(fragment)) {
1236 throw new IllegalStateException("Fragment already added: " + fragment);
1237 }
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001238 mAdded.add(fragment);
1239 fragment.mAdded = true;
1240 fragment.mRemoving = false;
Dianne Hackborn6c285972011-08-29 16:53:49 -07001241 if (fragment.mHasMenu && fragment.mMenuVisible) {
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001242 mNeedMenuInvalidate = true;
1243 }
1244 if (moveToStateNow) {
1245 moveToState(fragment);
1246 }
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001247 }
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001248 }
1249
Dianne Hackbornf121be72010-05-06 14:10:32 -07001250 public void removeFragment(Fragment fragment, int transition, int transitionStyle) {
Dianne Hackborn5e0d5952010-08-05 13:45:35 -07001251 if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001252 final boolean inactive = !fragment.isInBackStack();
1253 if (!fragment.mDetached || inactive) {
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07001254 if (false) {
1255 // Would be nice to catch a bad remove here, but we need
1256 // time to test this to make sure we aren't crashes cases
1257 // where it is not a problem.
1258 if (!mAdded.contains(fragment)) {
1259 throw new IllegalStateException("Fragment not added: " + fragment);
1260 }
1261 }
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07001262 if (mAdded != null) {
1263 mAdded.remove(fragment);
1264 }
Dianne Hackborn6c285972011-08-29 16:53:49 -07001265 if (fragment.mHasMenu && fragment.mMenuVisible) {
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001266 mNeedMenuInvalidate = true;
1267 }
1268 fragment.mAdded = false;
1269 fragment.mRemoving = true;
1270 moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
Dianne Hackbornee76efb2012-06-05 10:27:40 -07001271 transition, transitionStyle, false);
Dianne Hackborn5e0d5952010-08-05 13:45:35 -07001272 }
Dianne Hackbornf121be72010-05-06 14:10:32 -07001273 }
1274
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001275 public void hideFragment(Fragment fragment, int transition, int transitionStyle) {
1276 if (DEBUG) Log.v(TAG, "hide: " + fragment);
1277 if (!fragment.mHidden) {
1278 fragment.mHidden = true;
1279 if (fragment.mView != null) {
Adam Powell27562932013-06-07 10:16:08 -07001280 Animator anim = loadAnimator(fragment, transition, false,
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001281 transitionStyle);
1282 if (anim != null) {
Chet Haaseb20db3e2010-09-10 13:07:30 -07001283 anim.setTarget(fragment.mView);
Chet Haase61eb40d2010-12-28 13:59:17 -08001284 // Delay the actual hide operation until the animation finishes, otherwise
1285 // the fragment will just immediately disappear
1286 final Fragment finalFragment = fragment;
1287 anim.addListener(new AnimatorListenerAdapter() {
1288 @Override
1289 public void onAnimationEnd(Animator animation) {
Chet Haaseb29407f2011-01-11 14:09:34 -08001290 if (finalFragment.mView != null) {
1291 finalFragment.mView.setVisibility(View.GONE);
1292 }
Chet Haase61eb40d2010-12-28 13:59:17 -08001293 }
1294 });
Doris Liude9284d2015-05-22 15:41:46 -07001295 setHWLayerAnimListenerIfAlpha(finalFragment.mView, anim);
Chet Haase811ed1062010-08-06 10:38:15 -07001296 anim.start();
Chet Haasee646b28c2010-12-28 14:48:32 -08001297 } else {
1298 fragment.mView.setVisibility(View.GONE);
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001299 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001300 }
Dianne Hackborn6c285972011-08-29 16:53:49 -07001301 if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) {
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07001302 mNeedMenuInvalidate = true;
1303 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001304 fragment.onHiddenChanged(true);
1305 }
1306 }
1307
1308 public void showFragment(Fragment fragment, int transition, int transitionStyle) {
1309 if (DEBUG) Log.v(TAG, "show: " + fragment);
1310 if (fragment.mHidden) {
1311 fragment.mHidden = false;
1312 if (fragment.mView != null) {
Chet Haasea18a86b2010-09-07 13:20:00 -07001313 Animator anim = loadAnimator(fragment, transition, true,
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001314 transitionStyle);
1315 if (anim != null) {
Chet Haaseb20db3e2010-09-10 13:07:30 -07001316 anim.setTarget(fragment.mView);
Doris Liude9284d2015-05-22 15:41:46 -07001317 setHWLayerAnimListenerIfAlpha(fragment.mView, anim);
Chet Haase811ed1062010-08-06 10:38:15 -07001318 anim.start();
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001319 }
1320 fragment.mView.setVisibility(View.VISIBLE);
1321 }
Dianne Hackborn6c285972011-08-29 16:53:49 -07001322 if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) {
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07001323 mNeedMenuInvalidate = true;
1324 }
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001325 fragment.onHiddenChanged(false);
1326 }
1327 }
1328
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001329 public void detachFragment(Fragment fragment, int transition, int transitionStyle) {
1330 if (DEBUG) Log.v(TAG, "detach: " + fragment);
1331 if (!fragment.mDetached) {
1332 fragment.mDetached = true;
1333 if (fragment.mAdded) {
1334 // We are not already in back stack, so need to remove the fragment.
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07001335 if (mAdded != null) {
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07001336 if (DEBUG) Log.v(TAG, "remove from detach: " + fragment);
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07001337 mAdded.remove(fragment);
1338 }
Dianne Hackborn6c285972011-08-29 16:53:49 -07001339 if (fragment.mHasMenu && fragment.mMenuVisible) {
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001340 mNeedMenuInvalidate = true;
1341 }
1342 fragment.mAdded = false;
Dianne Hackbornee76efb2012-06-05 10:27:40 -07001343 moveToState(fragment, Fragment.CREATED, transition, transitionStyle, false);
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001344 }
1345 }
1346 }
1347
1348 public void attachFragment(Fragment fragment, int transition, int transitionStyle) {
1349 if (DEBUG) Log.v(TAG, "attach: " + fragment);
1350 if (fragment.mDetached) {
1351 fragment.mDetached = false;
1352 if (!fragment.mAdded) {
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07001353 if (mAdded == null) {
1354 mAdded = new ArrayList<Fragment>();
1355 }
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07001356 if (mAdded.contains(fragment)) {
1357 throw new IllegalStateException("Fragment already added: " + fragment);
1358 }
1359 if (DEBUG) Log.v(TAG, "add from attach: " + fragment);
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001360 mAdded.add(fragment);
1361 fragment.mAdded = true;
Dianne Hackborn6c285972011-08-29 16:53:49 -07001362 if (fragment.mHasMenu && fragment.mMenuVisible) {
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001363 mNeedMenuInvalidate = true;
1364 }
Dianne Hackbornee76efb2012-06-05 10:27:40 -07001365 moveToState(fragment, mCurState, transition, transitionStyle, false);
Dianne Hackborn16f6e892011-04-15 19:00:20 -07001366 }
1367 }
1368 }
1369
Dianne Hackbornf121be72010-05-06 14:10:32 -07001370 public Fragment findFragmentById(int id) {
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07001371 if (mAdded != null) {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001372 // First look through added fragments.
1373 for (int i=mAdded.size()-1; i>=0; i--) {
1374 Fragment f = mAdded.get(i);
1375 if (f != null && f.mFragmentId == id) {
1376 return f;
1377 }
1378 }
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07001379 }
1380 if (mActive != null) {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001381 // Now for any known fragment.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001382 for (int i=mActive.size()-1; i>=0; i--) {
1383 Fragment f = mActive.get(i);
1384 if (f != null && f.mFragmentId == id) {
Dianne Hackbornf121be72010-05-06 14:10:32 -07001385 return f;
1386 }
1387 }
1388 }
1389 return null;
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001390 }
1391
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001392 public Fragment findFragmentByTag(String tag) {
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07001393 if (mAdded != null && tag != null) {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001394 // First look through added fragments.
1395 for (int i=mAdded.size()-1; i>=0; i--) {
1396 Fragment f = mAdded.get(i);
1397 if (f != null && tag.equals(f.mTag)) {
1398 return f;
1399 }
1400 }
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07001401 }
1402 if (mActive != null && tag != null) {
Dianne Hackborn5ae74d62010-05-19 19:14:57 -07001403 // Now for any known fragment.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001404 for (int i=mActive.size()-1; i>=0; i--) {
1405 Fragment f = mActive.get(i);
1406 if (f != null && tag.equals(f.mTag)) {
1407 return f;
1408 }
1409 }
1410 }
1411 return null;
1412 }
1413
1414 public Fragment findFragmentByWho(String who) {
1415 if (mActive != null && who != null) {
1416 for (int i=mActive.size()-1; i>=0; i--) {
1417 Fragment f = mActive.get(i);
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001418 if (f != null && (f=f.findFragmentByWho(who)) != null) {
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001419 return f;
1420 }
1421 }
1422 }
1423 return null;
1424 }
1425
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001426 private void checkStateLoss() {
1427 if (mStateSaved) {
1428 throw new IllegalStateException(
1429 "Can not perform this action after onSaveInstanceState");
1430 }
1431 if (mNoTransactionsBecause != null) {
1432 throw new IllegalStateException(
1433 "Can not perform this action inside of " + mNoTransactionsBecause);
1434 }
1435 }
1436
Alan Viverette95a46092013-08-14 11:17:25 -07001437 /**
1438 * Adds an action to the queue of pending actions.
1439 *
1440 * @param action the action to add
1441 * @param allowStateLoss whether to allow loss of state information
1442 * @throws IllegalStateException if the activity has been destroyed
1443 */
Dianne Hackbornab36acb2010-11-05 14:12:11 -07001444 public void enqueueAction(Runnable action, boolean allowStateLoss) {
Dianne Hackborn6908cd12010-11-08 15:11:16 -08001445 if (!allowStateLoss) {
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001446 checkStateLoss();
Dianne Hackbornfb3cffe2010-10-25 17:08:56 -07001447 }
Dianne Hackborn445646c2010-06-25 15:52:59 -07001448 synchronized (this) {
Todd Kennedya5fc6f02015-04-14 18:22:54 -07001449 if (mDestroyed || mHost == null) {
Dianne Hackborn6908cd12010-11-08 15:11:16 -08001450 throw new IllegalStateException("Activity has been destroyed");
1451 }
Dianne Hackborn445646c2010-06-25 15:52:59 -07001452 if (mPendingActions == null) {
1453 mPendingActions = new ArrayList<Runnable>();
1454 }
1455 mPendingActions.add(action);
1456 if (mPendingActions.size() == 1) {
Todd Kennedya5fc6f02015-04-14 18:22:54 -07001457 mHost.getHandler().removeCallbacks(mExecCommit);
1458 mHost.getHandler().post(mExecCommit);
Dianne Hackborn445646c2010-06-25 15:52:59 -07001459 }
1460 }
1461 }
1462
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001463 public int allocBackStackIndex(BackStackRecord bse) {
Dianne Hackborndd913a52010-07-22 12:17:04 -07001464 synchronized (this) {
1465 if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) {
1466 if (mBackStackIndices == null) {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001467 mBackStackIndices = new ArrayList<BackStackRecord>();
Dianne Hackborndd913a52010-07-22 12:17:04 -07001468 }
1469 int index = mBackStackIndices.size();
1470 if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
1471 mBackStackIndices.add(bse);
1472 return index;
1473
1474 } else {
1475 int index = mAvailBackStackIndices.remove(mAvailBackStackIndices.size()-1);
1476 if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse);
1477 mBackStackIndices.set(index, bse);
1478 return index;
1479 }
1480 }
1481 }
1482
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001483 public void setBackStackIndex(int index, BackStackRecord bse) {
Dianne Hackborndd913a52010-07-22 12:17:04 -07001484 synchronized (this) {
1485 if (mBackStackIndices == null) {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001486 mBackStackIndices = new ArrayList<BackStackRecord>();
Dianne Hackborndd913a52010-07-22 12:17:04 -07001487 }
1488 int N = mBackStackIndices.size();
1489 if (index < N) {
1490 if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
1491 mBackStackIndices.set(index, bse);
1492 } else {
1493 while (N < index) {
1494 mBackStackIndices.add(null);
1495 if (mAvailBackStackIndices == null) {
1496 mAvailBackStackIndices = new ArrayList<Integer>();
1497 }
1498 if (DEBUG) Log.v(TAG, "Adding available back stack index " + N);
1499 mAvailBackStackIndices.add(N);
1500 N++;
1501 }
1502 if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse);
1503 mBackStackIndices.add(bse);
1504 }
1505 }
1506 }
1507
1508 public void freeBackStackIndex(int index) {
1509 synchronized (this) {
1510 mBackStackIndices.set(index, null);
1511 if (mAvailBackStackIndices == null) {
1512 mAvailBackStackIndices = new ArrayList<Integer>();
1513 }
1514 if (DEBUG) Log.v(TAG, "Freeing back stack index " + index);
1515 mAvailBackStackIndices.add(index);
1516 }
1517 }
1518
Adam Powell8585ed62016-02-04 15:38:20 -08001519 public void execSingleAction(Runnable action, boolean allowStateLoss) {
1520 if (mExecutingActions) {
1521 throw new IllegalStateException("FragmentManager is already executing transactions");
1522 }
1523
1524 if (Looper.myLooper() != mHost.getHandler().getLooper()) {
1525 throw new IllegalStateException("Must be called from main thread of fragment host");
1526 }
1527
Adam Powell3518fed2016-03-01 09:07:44 -08001528 if (!allowStateLoss) {
Adam Powell8585ed62016-02-04 15:38:20 -08001529 checkStateLoss();
1530 }
1531
1532 mExecutingActions = true;
1533 action.run();
1534 mExecutingActions = false;
1535
1536 doPendingDeferredStart();
1537 }
1538
Dianne Hackborn445646c2010-06-25 15:52:59 -07001539 /**
1540 * Only call from main thread!
1541 */
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001542 public boolean execPendingActions() {
Dianne Hackborn445646c2010-06-25 15:52:59 -07001543 if (mExecutingActions) {
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001544 throw new IllegalStateException("Recursive entry to executePendingTransactions");
Dianne Hackborn445646c2010-06-25 15:52:59 -07001545 }
1546
Todd Kennedya5fc6f02015-04-14 18:22:54 -07001547 if (Looper.myLooper() != mHost.getHandler().getLooper()) {
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001548 throw new IllegalStateException("Must be called from main thread of process");
1549 }
1550
1551 boolean didSomething = false;
1552
Dianne Hackborn445646c2010-06-25 15:52:59 -07001553 while (true) {
1554 int numActions;
1555
1556 synchronized (this) {
1557 if (mPendingActions == null || mPendingActions.size() == 0) {
Adam Powell78fed9b2011-11-07 10:45:34 -08001558 break;
Dianne Hackborn445646c2010-06-25 15:52:59 -07001559 }
1560
1561 numActions = mPendingActions.size();
1562 if (mTmpActions == null || mTmpActions.length < numActions) {
1563 mTmpActions = new Runnable[numActions];
1564 }
1565 mPendingActions.toArray(mTmpActions);
1566 mPendingActions.clear();
Todd Kennedya5fc6f02015-04-14 18:22:54 -07001567 mHost.getHandler().removeCallbacks(mExecCommit);
Dianne Hackborn445646c2010-06-25 15:52:59 -07001568 }
1569
1570 mExecutingActions = true;
1571 for (int i=0; i<numActions; i++) {
1572 mTmpActions[i].run();
Jeff Sharkey0d325282011-07-13 09:36:27 -07001573 mTmpActions[i] = null;
Dianne Hackborn445646c2010-06-25 15:52:59 -07001574 }
1575 mExecutingActions = false;
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001576 didSomething = true;
Dianne Hackborn445646c2010-06-25 15:52:59 -07001577 }
Adam Powell78fed9b2011-11-07 10:45:34 -08001578
Adam Powell8585ed62016-02-04 15:38:20 -08001579 doPendingDeferredStart();
1580
1581 return didSomething;
1582 }
1583
1584 void doPendingDeferredStart() {
Adam Powell78fed9b2011-11-07 10:45:34 -08001585 if (mHavePendingDeferredStart) {
1586 boolean loadersRunning = false;
1587 for (int i=0; i<mActive.size(); i++) {
1588 Fragment f = mActive.get(i);
1589 if (f != null && f.mLoaderManager != null) {
1590 loadersRunning |= f.mLoaderManager.hasRunningLoaders();
1591 }
1592 }
1593 if (!loadersRunning) {
1594 mHavePendingDeferredStart = false;
1595 startPendingDeferredFragments();
1596 }
1597 }
Dianne Hackborn445646c2010-06-25 15:52:59 -07001598 }
Adam Powell78fed9b2011-11-07 10:45:34 -08001599
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001600 void reportBackStackChanged() {
1601 if (mBackStackChangeListeners != null) {
1602 for (int i=0; i<mBackStackChangeListeners.size(); i++) {
1603 mBackStackChangeListeners.get(i).onBackStackChanged();
1604 }
1605 }
1606 }
1607
1608 void addBackStackState(BackStackRecord state) {
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001609 if (mBackStack == null) {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001610 mBackStack = new ArrayList<BackStackRecord>();
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001611 }
1612 mBackStack.add(state);
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001613 reportBackStackChanged();
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001614 }
1615
Dianne Hackborndd913a52010-07-22 12:17:04 -07001616 boolean popBackStackState(Handler handler, String name, int id, int flags) {
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001617 if (mBackStack == null) {
1618 return false;
1619 }
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001620 if (name == null && id < 0 && (flags&POP_BACK_STACK_INCLUSIVE) == 0) {
Dianne Hackbornf121be72010-05-06 14:10:32 -07001621 int last = mBackStack.size()-1;
1622 if (last < 0) {
1623 return false;
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001624 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001625 final BackStackRecord bss = mBackStack.remove(last);
George Mountc03da0e2014-08-22 17:04:02 -07001626 SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
1627 SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
George Mounta7245b42016-02-10 17:03:32 -08001628 if (mCurState >= Fragment.CREATED) {
1629 bss.calculateBackFragments(firstOutFragments, lastInFragments);
1630 }
George Mountc03da0e2014-08-22 17:04:02 -07001631 bss.popFromBackStack(true, null, firstOutFragments, lastInFragments);
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001632 reportBackStackChanged();
Dianne Hackbornf121be72010-05-06 14:10:32 -07001633 } else {
Dianne Hackbornb3cf10f2010-08-03 13:07:11 -07001634 int index = -1;
1635 if (name != null || id >= 0) {
1636 // If a name or ID is specified, look for that place in
1637 // the stack.
1638 index = mBackStack.size()-1;
1639 while (index >= 0) {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001640 BackStackRecord bss = mBackStack.get(index);
Dianne Hackbornb3cf10f2010-08-03 13:07:11 -07001641 if (name != null && name.equals(bss.getName())) {
1642 break;
1643 }
1644 if (id >= 0 && id == bss.mIndex) {
1645 break;
1646 }
1647 index--;
Dianne Hackbornf121be72010-05-06 14:10:32 -07001648 }
Dianne Hackbornb3cf10f2010-08-03 13:07:11 -07001649 if (index < 0) {
1650 return false;
Dianne Hackborndd913a52010-07-22 12:17:04 -07001651 }
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001652 if ((flags&POP_BACK_STACK_INCLUSIVE) != 0) {
Dianne Hackbornb3cf10f2010-08-03 13:07:11 -07001653 index--;
1654 // Consume all following entries that match.
1655 while (index >= 0) {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001656 BackStackRecord bss = mBackStack.get(index);
Dianne Hackbornb3cf10f2010-08-03 13:07:11 -07001657 if ((name != null && name.equals(bss.getName()))
1658 || (id >= 0 && id == bss.mIndex)) {
1659 index--;
1660 continue;
1661 }
1662 break;
1663 }
1664 }
Dianne Hackborndd913a52010-07-22 12:17:04 -07001665 }
1666 if (index == mBackStack.size()-1) {
Dianne Hackbornf121be72010-05-06 14:10:32 -07001667 return false;
1668 }
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001669 final ArrayList<BackStackRecord> states
1670 = new ArrayList<BackStackRecord>();
Dianne Hackbornf121be72010-05-06 14:10:32 -07001671 for (int i=mBackStack.size()-1; i>index; i--) {
1672 states.add(mBackStack.remove(i));
1673 }
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001674 final int LAST = states.size()-1;
George Mountc03da0e2014-08-22 17:04:02 -07001675 SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
1676 SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
George Mounta7245b42016-02-10 17:03:32 -08001677 if (mCurState >= Fragment.CREATED) {
1678 for (int i = 0; i <= LAST; i++) {
1679 states.get(i).calculateBackFragments(firstOutFragments, lastInFragments);
1680 }
George Mountc03da0e2014-08-22 17:04:02 -07001681 }
George Mountd4c3c912014-06-09 12:31:34 -07001682 BackStackRecord.TransitionState state = null;
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001683 for (int i=0; i<=LAST; i++) {
1684 if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
George Mountc03da0e2014-08-22 17:04:02 -07001685 state = states.get(i).popFromBackStack(i == LAST, state,
1686 firstOutFragments, lastInFragments);
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001687 }
1688 reportBackStackChanged();
Dianne Hackbornf121be72010-05-06 14:10:32 -07001689 }
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07001690 return true;
1691 }
Adam Powell44ba79e2016-02-04 16:20:37 -08001692
1693 FragmentManagerNonConfig retainNonConfig() {
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001694 ArrayList<Fragment> fragments = null;
Adam Powell44ba79e2016-02-04 16:20:37 -08001695 ArrayList<FragmentManagerNonConfig> childFragments = null;
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001696 if (mActive != null) {
1697 for (int i=0; i<mActive.size(); i++) {
1698 Fragment f = mActive.get(i);
Adam Powell44ba79e2016-02-04 16:20:37 -08001699 if (f != null) {
1700 if (f.mRetainInstance) {
1701 if (fragments == null) {
1702 fragments = new ArrayList<>();
1703 }
1704 fragments.add(f);
1705 f.mRetaining = true;
1706 f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1;
1707 if (DEBUG) Log.v(TAG, "retainNonConfig: keeping retained " + f);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001708 }
Adam Powell44ba79e2016-02-04 16:20:37 -08001709 boolean addedChild = false;
1710 if (f.mChildFragmentManager != null) {
1711 FragmentManagerNonConfig child = f.mChildFragmentManager.retainNonConfig();
1712 if (child != null) {
1713 if (childFragments == null) {
1714 childFragments = new ArrayList<>();
1715 for (int j = 0; j < i; j++) {
1716 childFragments.add(null);
1717 }
1718 }
1719 childFragments.add(child);
1720 addedChild = true;
1721 }
1722 }
1723 if (childFragments != null && !addedChild) {
1724 childFragments.add(null);
1725 }
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001726 }
1727 }
1728 }
Adam Powell44ba79e2016-02-04 16:20:37 -08001729 if (fragments == null && childFragments == null) {
1730 return null;
1731 }
1732 return new FragmentManagerNonConfig(fragments, childFragments);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001733 }
1734
1735 void saveFragmentViewState(Fragment f) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001736 if (f.mView == null) {
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001737 return;
1738 }
1739 if (mStateArray == null) {
1740 mStateArray = new SparseArray<Parcelable>();
Dianne Hackbornb46ed762011-06-02 18:33:15 -07001741 } else {
1742 mStateArray.clear();
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001743 }
1744 f.mView.saveHierarchyState(mStateArray);
1745 if (mStateArray.size() > 0) {
1746 f.mSavedViewState = mStateArray;
1747 mStateArray = null;
1748 }
1749 }
1750
Dianne Hackbornb46ed762011-06-02 18:33:15 -07001751 Bundle saveFragmentBasicState(Fragment f) {
1752 Bundle result = null;
1753
1754 if (mStateBundle == null) {
1755 mStateBundle = new Bundle();
1756 }
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07001757 f.performSaveInstanceState(mStateBundle);
Dianne Hackbornb46ed762011-06-02 18:33:15 -07001758 if (!mStateBundle.isEmpty()) {
1759 result = mStateBundle;
1760 mStateBundle = null;
1761 }
1762
1763 if (f.mView != null) {
1764 saveFragmentViewState(f);
Dianne Hackborn13332762011-06-03 17:34:45 -07001765 }
1766 if (f.mSavedViewState != null) {
1767 if (result == null) {
1768 result = new Bundle();
Dianne Hackbornb46ed762011-06-02 18:33:15 -07001769 }
Dianne Hackborn13332762011-06-03 17:34:45 -07001770 result.putSparseParcelableArray(
1771 FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
Dianne Hackbornb46ed762011-06-02 18:33:15 -07001772 }
Adam Powell78fed9b2011-11-07 10:45:34 -08001773 if (!f.mUserVisibleHint) {
Jake Wharton258029e2012-04-22 17:17:01 -04001774 if (result == null) {
1775 result = new Bundle();
1776 }
Adam Powell78fed9b2011-11-07 10:45:34 -08001777 // Only add this if it's not the default value
1778 result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
1779 }
Dianne Hackbornb46ed762011-06-02 18:33:15 -07001780
1781 return result;
1782 }
1783
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001784 Parcelable saveAllState() {
Dianne Hackborn3a57fb92010-11-15 17:58:52 -08001785 // Make sure all pending operations have now been executed to get
1786 // our state update-to-date.
1787 execPendingActions();
1788
Dianne Hackborn3e449ce2010-09-11 20:52:31 -07001789 mStateSaved = true;
1790
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001791 if (mActive == null || mActive.size() <= 0) {
1792 return null;
1793 }
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001794
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001795 // First collect all active fragments.
1796 int N = mActive.size();
1797 FragmentState[] active = new FragmentState[N];
1798 boolean haveFragments = false;
1799 for (int i=0; i<N; i++) {
1800 Fragment f = mActive.get(i);
1801 if (f != null) {
Dianne Hackborn61af8a82012-05-30 16:38:30 -07001802 if (f.mIndex < 0) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07001803 throwException(new IllegalStateException(
1804 "Failure saving state: active " + f
1805 + " has cleared index: " + f.mIndex));
Dianne Hackborn61af8a82012-05-30 16:38:30 -07001806 }
1807
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001808 haveFragments = true;
Dianne Hackborn61af8a82012-05-30 16:38:30 -07001809
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001810 FragmentState fs = new FragmentState(f);
1811 active[i] = fs;
1812
Dianne Hackborn625ac272010-09-17 18:29:22 -07001813 if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
Dianne Hackbornb46ed762011-06-02 18:33:15 -07001814 fs.mSavedFragmentState = saveFragmentBasicState(f);
Dianne Hackborn625ac272010-09-17 18:29:22 -07001815
1816 if (f.mTarget != null) {
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -08001817 if (f.mTarget.mIndex < 0) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07001818 throwException(new IllegalStateException(
1819 "Failure saving state: " + f
1820 + " has target not in fragment manager: " + f.mTarget));
Dianne Hackborn5d9d03a2011-01-24 13:15:09 -08001821 }
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001822 if (fs.mSavedFragmentState == null) {
1823 fs.mSavedFragmentState = new Bundle();
1824 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07001825 putFragment(fs.mSavedFragmentState,
1826 FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
1827 if (f.mTargetRequestCode != 0) {
1828 fs.mSavedFragmentState.putInt(
1829 FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
1830 f.mTargetRequestCode);
1831 }
Dianne Hackborndef15372010-08-15 12:43:52 -07001832 }
Dianne Hackborndef15372010-08-15 12:43:52 -07001833
Dianne Hackborn625ac272010-09-17 18:29:22 -07001834 } else {
1835 fs.mSavedFragmentState = f.mSavedFragmentState;
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001836 }
1837
Dianne Hackbornb7a2e472010-08-12 16:20:42 -07001838 if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
1839 + fs.mSavedFragmentState);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001840 }
1841 }
1842
1843 if (!haveFragments) {
Dianne Hackbornb7a2e472010-08-12 16:20:42 -07001844 if (DEBUG) Log.v(TAG, "saveAllState: no fragments!");
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001845 return null;
1846 }
1847
1848 int[] added = null;
1849 BackStackState[] backStack = null;
1850
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001851 // Build list of currently added fragments.
Dianne Hackborn625ac272010-09-17 18:29:22 -07001852 if (mAdded != null) {
1853 N = mAdded.size();
1854 if (N > 0) {
1855 added = new int[N];
1856 for (int i=0; i<N; i++) {
1857 added[i] = mAdded.get(i).mIndex;
Dianne Hackborn61af8a82012-05-30 16:38:30 -07001858 if (added[i] < 0) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07001859 throwException(new IllegalStateException(
1860 "Failure saving state: active " + mAdded.get(i)
1861 + " has cleared index: " + added[i]));
Dianne Hackborn61af8a82012-05-30 16:38:30 -07001862 }
Dianne Hackborn625ac272010-09-17 18:29:22 -07001863 if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
1864 + ": " + mAdded.get(i));
1865 }
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001866 }
1867 }
1868
1869 // Now save back stack.
1870 if (mBackStack != null) {
1871 N = mBackStack.size();
1872 if (N > 0) {
1873 backStack = new BackStackState[N];
1874 for (int i=0; i<N; i++) {
1875 backStack[i] = new BackStackState(this, mBackStack.get(i));
Dianne Hackbornb7a2e472010-08-12 16:20:42 -07001876 if (DEBUG) Log.v(TAG, "saveAllState: adding back stack #" + i
1877 + ": " + mBackStack.get(i));
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001878 }
1879 }
1880 }
1881
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001882 FragmentManagerState fms = new FragmentManagerState();
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001883 fms.mActive = active;
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001884 fms.mAdded = added;
1885 fms.mBackStack = backStack;
1886 return fms;
1887 }
1888
Adam Powell44ba79e2016-02-04 16:20:37 -08001889 void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001890 // If there is no saved state at all, then there can not be
1891 // any nonConfig fragments either, so that is that.
1892 if (state == null) return;
1893 FragmentManagerState fms = (FragmentManagerState)state;
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001894 if (fms.mActive == null) return;
Adam Powell44ba79e2016-02-04 16:20:37 -08001895
1896 List<FragmentManagerNonConfig> childNonConfigs = null;
1897
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001898 // First re-attach any non-config instances we are retaining back
1899 // to their saved state, so we don't try to instantiate them again.
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001900 if (nonConfig != null) {
Adam Powell44ba79e2016-02-04 16:20:37 -08001901 List<Fragment> nonConfigFragments = nonConfig.getFragments();
1902 childNonConfigs = nonConfig.getChildNonConfigs();
1903 final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;
1904 for (int i = 0; i < count; i++) {
1905 Fragment f = nonConfigFragments.get(i);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -07001906 if (DEBUG) Log.v(TAG, "restoreAllState: re-attaching retained " + f);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001907 FragmentState fs = fms.mActive[f.mIndex];
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001908 fs.mInstance = f;
1909 f.mSavedViewState = null;
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001910 f.mBackStackNesting = 0;
Dianne Hackborn625ac272010-09-17 18:29:22 -07001911 f.mInLayout = false;
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001912 f.mAdded = false;
Dianne Hackbornf9302322011-06-14 18:36:14 -07001913 f.mTarget = null;
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001914 if (fs.mSavedFragmentState != null) {
Todd Kennedya5fc6f02015-04-14 18:22:54 -07001915 fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001916 f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
Dianne Hackborndef15372010-08-15 12:43:52 -07001917 FragmentManagerImpl.VIEW_STATE_TAG);
Craig Mautner33acfbe2014-06-28 14:00:53 -07001918 f.mSavedFragmentState = fs.mSavedFragmentState;
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001919 }
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001920 }
1921 }
1922
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001923 // Build the full list of active fragments, instantiating them from
1924 // their saved state.
Adam Powell44ba79e2016-02-04 16:20:37 -08001925 mActive = new ArrayList<>(fms.mActive.length);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001926 if (mAvailIndices != null) {
1927 mAvailIndices.clear();
1928 }
1929 for (int i=0; i<fms.mActive.length; i++) {
1930 FragmentState fs = fms.mActive[i];
1931 if (fs != null) {
Adam Powell44ba79e2016-02-04 16:20:37 -08001932 FragmentManagerNonConfig childNonConfig = null;
1933 if (childNonConfigs != null && i < childNonConfigs.size()) {
1934 childNonConfig = childNonConfigs.get(i);
1935 }
1936 Fragment f = fs.instantiate(mHost, mParent, childNonConfig);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07001937 if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
Dianne Hackbornb7a2e472010-08-12 16:20:42 -07001938 mActive.add(f);
Dianne Hackborn30d71892010-12-11 10:37:55 -08001939 // Now that the fragment is instantiated (or came from being
1940 // retained above), clear mInstance in case we end up re-restoring
1941 // from this FragmentState again.
1942 fs.mInstance = null;
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001943 } else {
1944 mActive.add(null);
1945 if (mAvailIndices == null) {
Adam Powell44ba79e2016-02-04 16:20:37 -08001946 mAvailIndices = new ArrayList<>();
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001947 }
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07001948 if (DEBUG) Log.v(TAG, "restoreAllState: avail #" + i);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001949 mAvailIndices.add(i);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001950 }
1951 }
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001952
Dianne Hackborn3e449ce2010-09-11 20:52:31 -07001953 // Update the target of all retained fragments.
1954 if (nonConfig != null) {
Adam Powell44ba79e2016-02-04 16:20:37 -08001955 List<Fragment> nonConfigFragments = nonConfig.getFragments();
1956 final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;
1957 for (int i = 0; i < count; i++) {
1958 Fragment f = nonConfigFragments.get(i);
Dianne Hackbornf9302322011-06-14 18:36:14 -07001959 if (f.mTargetIndex >= 0) {
1960 if (f.mTargetIndex < mActive.size()) {
1961 f.mTarget = mActive.get(f.mTargetIndex);
Dianne Hackborn3e449ce2010-09-11 20:52:31 -07001962 } else {
1963 Log.w(TAG, "Re-attaching retained fragment " + f
Dianne Hackbornf9302322011-06-14 18:36:14 -07001964 + " target no longer exists: " + f.mTargetIndex);
Dianne Hackborn3e449ce2010-09-11 20:52:31 -07001965 f.mTarget = null;
1966 }
1967 }
1968 }
1969 }
1970
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001971 // Build the list of currently added fragments.
1972 if (fms.mAdded != null) {
1973 mAdded = new ArrayList<Fragment>(fms.mAdded.length);
1974 for (int i=0; i<fms.mAdded.length; i++) {
1975 Fragment f = mActive.get(fms.mAdded[i]);
1976 if (f == null) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07001977 throwException(new IllegalStateException(
1978 "No instantiated fragment for index #" + fms.mAdded[i]));
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001979 }
1980 f.mAdded = true;
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07001981 if (DEBUG) Log.v(TAG, "restoreAllState: added #" + i + ": " + f);
1982 if (mAdded.contains(f)) {
1983 throw new IllegalStateException("Already added!");
1984 }
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001985 mAdded.add(f);
1986 }
1987 } else {
1988 mAdded = null;
1989 }
1990
1991 // Build the back stack.
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001992 if (fms.mBackStack != null) {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001993 mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001994 for (int i=0; i<fms.mBackStack.length; i++) {
Dianne Hackbornc6669ca2010-09-16 01:33:24 -07001995 BackStackRecord bse = fms.mBackStack[i].instantiate(this);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07001996 if (DEBUG) {
1997 Log.v(TAG, "restoreAllState: back stack #" + i
Dianne Hackbornb7a2e472010-08-12 16:20:42 -07001998 + " (index " + bse.mIndex + "): " + bse);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07001999 LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
Dianne Hackborn8c841092013-06-24 13:46:13 -07002000 PrintWriter pw = new FastPrintWriter(logw, false, 1024);
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07002001 bse.dump(" ", pw, false);
Dianne Hackborn8c841092013-06-24 13:46:13 -07002002 pw.flush();
Dianne Hackbornf43a33c2012-09-27 00:48:11 -07002003 }
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07002004 mBackStack.add(bse);
Dianne Hackborndd913a52010-07-22 12:17:04 -07002005 if (bse.mIndex >= 0) {
2006 setBackStackIndex(bse.mIndex, bse);
2007 }
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07002008 }
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07002009 } else {
2010 mBackStack = null;
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07002011 }
2012 }
2013
Todd Kennedya5fc6f02015-04-14 18:22:54 -07002014 public void attachController(FragmentHostCallback<?> host, FragmentContainer container,
2015 Fragment parent) {
2016 if (mHost != null) throw new IllegalStateException("Already attached");
2017 mHost = host;
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002018 mContainer = container;
2019 mParent = parent;
Dianne Hackborn2dedce62010-04-15 14:45:25 -07002020 }
2021
Dianne Hackbornfb3cffe2010-10-25 17:08:56 -07002022 public void noteStateNotSaved() {
2023 mStateSaved = false;
2024 }
2025
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07002026 public void dispatchCreate() {
Dianne Hackborn3e449ce2010-09-11 20:52:31 -07002027 mStateSaved = false;
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07002028 moveToState(Fragment.CREATED, false);
Dianne Hackborn2dedce62010-04-15 14:45:25 -07002029 }
2030
Dianne Hackbornc8017682010-07-06 13:34:38 -07002031 public void dispatchActivityCreated() {
Dianne Hackborn3e449ce2010-09-11 20:52:31 -07002032 mStateSaved = false;
Dianne Hackbornc8017682010-07-06 13:34:38 -07002033 moveToState(Fragment.ACTIVITY_CREATED, false);
2034 }
2035
Dianne Hackborn2dedce62010-04-15 14:45:25 -07002036 public void dispatchStart() {
Dianne Hackborn3e449ce2010-09-11 20:52:31 -07002037 mStateSaved = false;
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07002038 moveToState(Fragment.STARTED, false);
Dianne Hackborn2dedce62010-04-15 14:45:25 -07002039 }
2040
2041 public void dispatchResume() {
Dianne Hackborn3e449ce2010-09-11 20:52:31 -07002042 mStateSaved = false;
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07002043 moveToState(Fragment.RESUMED, false);
Dianne Hackborn2dedce62010-04-15 14:45:25 -07002044 }
2045
2046 public void dispatchPause() {
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07002047 moveToState(Fragment.STARTED, false);
Dianne Hackborn2dedce62010-04-15 14:45:25 -07002048 }
2049
2050 public void dispatchStop() {
Dianne Hackborn16f6e892011-04-15 19:00:20 -07002051 moveToState(Fragment.STOPPED, false);
Dianne Hackborn2dedce62010-04-15 14:45:25 -07002052 }
2053
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002054 public void dispatchDestroyView() {
2055 moveToState(Fragment.CREATED, false);
2056 }
Dianne Hackborn1b8ecc52012-09-08 17:03:52 -07002057
Dianne Hackborn2dedce62010-04-15 14:45:25 -07002058 public void dispatchDestroy() {
Dianne Hackbornd173fa32010-12-23 13:58:22 -08002059 mDestroyed = true;
Dianne Hackbornc6938232011-07-21 16:25:26 -07002060 execPendingActions();
Dianne Hackbornba51c3d2010-05-05 18:49:48 -07002061 moveToState(Fragment.INITIALIZING, false);
Todd Kennedya5fc6f02015-04-14 18:22:54 -07002062 mHost = null;
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002063 mContainer = null;
2064 mParent = null;
Dianne Hackborn2dedce62010-04-15 14:45:25 -07002065 }
Wale Ogunwale7c796812016-01-29 21:13:50 -08002066
2067 public void dispatchMultiWindowChanged(boolean inMultiWindow) {
2068 if (mAdded == null) {
2069 return;
2070 }
2071 for (int i = mAdded.size() - 1; i >= 0; --i) {
2072 final Fragment f = mAdded.get(i);
2073 if (f != null) {
2074 f.performMultiWindowChanged(inMultiWindow);
2075 }
2076 }
2077 }
2078
2079 public void dispatchPictureInPictureChanged(boolean inPictureInPicture) {
2080 if (mAdded == null) {
2081 return;
2082 }
2083 for (int i = mAdded.size() - 1; i >= 0; --i) {
2084 final Fragment f = mAdded.get(i);
2085 if (f != null) {
2086 f.performPictureInPictureChanged(inPictureInPicture);
2087 }
2088 }
2089 }
2090
Dianne Hackborn9d071802010-12-08 14:49:15 -08002091 public void dispatchConfigurationChanged(Configuration newConfig) {
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07002092 if (mAdded != null) {
Dianne Hackborn9d071802010-12-08 14:49:15 -08002093 for (int i=0; i<mAdded.size(); i++) {
2094 Fragment f = mAdded.get(i);
2095 if (f != null) {
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002096 f.performConfigurationChanged(newConfig);
Dianne Hackborn9d071802010-12-08 14:49:15 -08002097 }
2098 }
2099 }
2100 }
2101
2102 public void dispatchLowMemory() {
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07002103 if (mAdded != null) {
Dianne Hackborn9d071802010-12-08 14:49:15 -08002104 for (int i=0; i<mAdded.size(); i++) {
2105 Fragment f = mAdded.get(i);
2106 if (f != null) {
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002107 f.performLowMemory();
Dianne Hackborn9d071802010-12-08 14:49:15 -08002108 }
2109 }
2110 }
2111 }
2112
Dianne Hackbornc68c9132011-07-29 01:25:18 -07002113 public void dispatchTrimMemory(int level) {
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07002114 if (mAdded != null) {
Dianne Hackbornc68c9132011-07-29 01:25:18 -07002115 for (int i=0; i<mAdded.size(); i++) {
2116 Fragment f = mAdded.get(i);
2117 if (f != null) {
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002118 f.performTrimMemory(level);
Dianne Hackbornc68c9132011-07-29 01:25:18 -07002119 }
2120 }
2121 }
2122 }
2123
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002124 public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
2125 boolean show = false;
Dianne Hackborn8eb2e242010-11-01 12:31:24 -07002126 ArrayList<Fragment> newMenus = null;
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07002127 if (mAdded != null) {
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002128 for (int i=0; i<mAdded.size(); i++) {
2129 Fragment f = mAdded.get(i);
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002130 if (f != null) {
2131 if (f.performCreateOptionsMenu(menu, inflater)) {
2132 show = true;
2133 if (newMenus == null) {
2134 newMenus = new ArrayList<Fragment>();
2135 }
2136 newMenus.add(f);
Dianne Hackborn8eb2e242010-11-01 12:31:24 -07002137 }
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002138 }
2139 }
2140 }
Dianne Hackborn8eb2e242010-11-01 12:31:24 -07002141
2142 if (mCreatedMenus != null) {
2143 for (int i=0; i<mCreatedMenus.size(); i++) {
2144 Fragment f = mCreatedMenus.get(i);
2145 if (newMenus == null || !newMenus.contains(f)) {
2146 f.onDestroyOptionsMenu();
2147 }
2148 }
2149 }
2150
2151 mCreatedMenus = newMenus;
2152
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002153 return show;
2154 }
2155
2156 public boolean dispatchPrepareOptionsMenu(Menu menu) {
2157 boolean show = false;
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07002158 if (mAdded != null) {
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002159 for (int i=0; i<mAdded.size(); i++) {
2160 Fragment f = mAdded.get(i);
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002161 if (f != null) {
2162 if (f.performPrepareOptionsMenu(menu)) {
2163 show = true;
2164 }
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002165 }
2166 }
2167 }
2168 return show;
2169 }
2170
2171 public boolean dispatchOptionsItemSelected(MenuItem item) {
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07002172 if (mAdded != null) {
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002173 for (int i=0; i<mAdded.size(); i++) {
2174 Fragment f = mAdded.get(i);
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002175 if (f != null) {
2176 if (f.performOptionsItemSelected(item)) {
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002177 return true;
2178 }
2179 }
2180 }
2181 }
2182 return false;
2183 }
2184
Dianne Hackborn5ddd1272010-06-12 10:15:28 -07002185 public boolean dispatchContextItemSelected(MenuItem item) {
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07002186 if (mAdded != null) {
Dianne Hackborn5ddd1272010-06-12 10:15:28 -07002187 for (int i=0; i<mAdded.size(); i++) {
2188 Fragment f = mAdded.get(i);
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002189 if (f != null) {
2190 if (f.performContextItemSelected(item)) {
Dianne Hackborn5ddd1272010-06-12 10:15:28 -07002191 return true;
2192 }
2193 }
2194 }
2195 }
2196 return false;
2197 }
2198
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002199 public void dispatchOptionsMenuClosed(Menu menu) {
Dianne Hackbornacdfbcc2012-06-19 15:07:05 -07002200 if (mAdded != null) {
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002201 for (int i=0; i<mAdded.size(); i++) {
2202 Fragment f = mAdded.get(i);
Dianne Hackborn62bea2f2012-09-04 18:48:15 -07002203 if (f != null) {
2204 f.performOptionsMenuClosed(menu);
Dianne Hackbornb31e84bc2010-06-08 18:04:35 -07002205 }
2206 }
2207 }
2208 }
Adam Powellf0f5fff2011-08-01 13:42:50 -07002209
2210 @Override
2211 public void invalidateOptionsMenu() {
Todd Kennedya5fc6f02015-04-14 18:22:54 -07002212 if (mHost != null && mCurState == Fragment.RESUMED) {
2213 mHost.onInvalidateOptionsMenu();
Adam Powellf0f5fff2011-08-01 13:42:50 -07002214 } else {
2215 mNeedMenuInvalidate = true;
2216 }
2217 }
2218
Dianne Hackbornf121be72010-05-06 14:10:32 -07002219 public static int reverseTransit(int transit) {
2220 int rev = 0;
2221 switch (transit) {
Chet Haase811ed1062010-08-06 10:38:15 -07002222 case FragmentTransaction.TRANSIT_FRAGMENT_OPEN:
2223 rev = FragmentTransaction.TRANSIT_FRAGMENT_CLOSE;
Dianne Hackbornf121be72010-05-06 14:10:32 -07002224 break;
Chet Haase811ed1062010-08-06 10:38:15 -07002225 case FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:
2226 rev = FragmentTransaction.TRANSIT_FRAGMENT_OPEN;
Dianne Hackbornf121be72010-05-06 14:10:32 -07002227 break;
Dianne Hackborn327fbd22011-01-17 14:38:50 -08002228 case FragmentTransaction.TRANSIT_FRAGMENT_FADE:
2229 rev = FragmentTransaction.TRANSIT_FRAGMENT_FADE;
Chet Haase9ff82bf2010-10-05 14:30:51 -07002230 break;
Dianne Hackbornf121be72010-05-06 14:10:32 -07002231 }
2232 return rev;
2233
2234 }
2235
2236 public static int transitToStyleIndex(int transit, boolean enter) {
2237 int animAttr = -1;
2238 switch (transit) {
Chet Haase811ed1062010-08-06 10:38:15 -07002239 case FragmentTransaction.TRANSIT_FRAGMENT_OPEN:
Dianne Hackbornf121be72010-05-06 14:10:32 -07002240 animAttr = enter
Chet Haase811ed1062010-08-06 10:38:15 -07002241 ? com.android.internal.R.styleable.FragmentAnimation_fragmentOpenEnterAnimation
2242 : com.android.internal.R.styleable.FragmentAnimation_fragmentOpenExitAnimation;
Dianne Hackbornf121be72010-05-06 14:10:32 -07002243 break;
Chet Haase811ed1062010-08-06 10:38:15 -07002244 case FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:
Dianne Hackbornf121be72010-05-06 14:10:32 -07002245 animAttr = enter
Chet Haase811ed1062010-08-06 10:38:15 -07002246 ? com.android.internal.R.styleable.FragmentAnimation_fragmentCloseEnterAnimation
2247 : com.android.internal.R.styleable.FragmentAnimation_fragmentCloseExitAnimation;
Dianne Hackbornf121be72010-05-06 14:10:32 -07002248 break;
Dianne Hackborn327fbd22011-01-17 14:38:50 -08002249 case FragmentTransaction.TRANSIT_FRAGMENT_FADE:
Chet Haase9ff82bf2010-10-05 14:30:51 -07002250 animAttr = enter
Dianne Hackborn327fbd22011-01-17 14:38:50 -08002251 ? com.android.internal.R.styleable.FragmentAnimation_fragmentFadeEnterAnimation
2252 : com.android.internal.R.styleable.FragmentAnimation_fragmentFadeExitAnimation;
Chet Haase9ff82bf2010-10-05 14:30:51 -07002253 break;
Dianne Hackbornf121be72010-05-06 14:10:32 -07002254 }
2255 return animAttr;
2256 }
Adam Powell371a8092014-06-20 12:51:12 -07002257
2258 @Override
2259 public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
2260 if (!"fragment".equals(name)) {
2261 return null;
2262 }
2263
2264 String fname = attrs.getAttributeValue(null, "class");
2265 TypedArray a =
2266 context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Fragment);
2267 if (fname == null) {
2268 fname = a.getString(com.android.internal.R.styleable.Fragment_name);
2269 }
2270 int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID);
2271 String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
2272 a.recycle();
2273
2274 int containerId = parent != null ? parent.getId() : 0;
2275 if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
2276 throw new IllegalArgumentException(attrs.getPositionDescription()
2277 + ": Must specify unique android:id, android:tag, or have a parent with"
2278 + " an id for " + fname);
2279 }
2280
2281 // If we restored from a previous state, we may already have
2282 // instantiated this fragment from the state and should use
2283 // that instance instead of making a new one.
2284 Fragment fragment = id != View.NO_ID ? findFragmentById(id) : null;
2285 if (fragment == null && tag != null) {
2286 fragment = findFragmentByTag(tag);
2287 }
2288 if (fragment == null && containerId != View.NO_ID) {
2289 fragment = findFragmentById(containerId);
2290 }
2291
2292 if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"
2293 + Integer.toHexString(id) + " fname=" + fname
2294 + " existing=" + fragment);
2295 if (fragment == null) {
2296 fragment = Fragment.instantiate(context, fname);
2297 fragment.mFromLayout = true;
2298 fragment.mFragmentId = id != 0 ? id : containerId;
2299 fragment.mContainerId = containerId;
2300 fragment.mTag = tag;
2301 fragment.mInLayout = true;
2302 fragment.mFragmentManager = this;
Todd Kennedy0aa69b72015-08-31 14:10:04 -07002303 fragment.mHost = mHost;
Todd Kennedy434bd652015-05-04 12:29:50 -07002304 fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
Adam Powell371a8092014-06-20 12:51:12 -07002305 addFragment(fragment, true);
2306 } else if (fragment.mInLayout) {
2307 // A fragment already exists and it is not one we restored from
2308 // previous state.
2309 throw new IllegalArgumentException(attrs.getPositionDescription()
2310 + ": Duplicate id 0x" + Integer.toHexString(id)
2311 + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
2312 + " with another fragment for " + fname);
2313 } else {
2314 // This fragment was retained from a previous instance; get it
2315 // going now.
2316 fragment.mInLayout = true;
Todd Kennedyac0e6ca2015-10-19 12:48:55 -07002317 fragment.mHost = mHost;
Adam Powell371a8092014-06-20 12:51:12 -07002318 // If this fragment is newly instantiated (either right now, or
2319 // from last saved state), then give it the attributes to
2320 // initialize itself.
2321 if (!fragment.mRetaining) {
Todd Kennedy434bd652015-05-04 12:29:50 -07002322 fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
Adam Powell371a8092014-06-20 12:51:12 -07002323 }
2324 }
2325
2326 // If we haven't finished entering the CREATED state ourselves yet,
2327 // push the inflated child fragment along.
2328 if (mCurState < Fragment.CREATED && fragment.mFromLayout) {
2329 moveToState(fragment, Fragment.CREATED, 0, 0, false);
2330 } else {
2331 moveToState(fragment);
2332 }
2333
2334 if (fragment.mView == null) {
2335 throw new IllegalStateException("Fragment " + fname
2336 + " did not create a view.");
2337 }
2338 if (id != 0) {
2339 fragment.mView.setId(id);
2340 }
2341 if (fragment.mView.getTag() == null) {
2342 fragment.mView.setTag(tag);
2343 }
2344 return fragment.mView;
2345 }
2346
2347 @Override
2348 public View onCreateView(String name, Context context, AttributeSet attrs) {
2349 return null;
2350 }
2351
2352 LayoutInflater.Factory2 getLayoutInflaterFactory() {
2353 return this;
2354 }
Dianne Hackborn2dedce62010-04-15 14:45:25 -07002355}