From f930232fd1c8d301d91853c8fe5dca43979ac807 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Tue, 14 Jun 2011 18:36:14 -0700 Subject: [PATCH] Fix a major problem in fragment lifecycle. When animating away a fragment, we were not putting it through the last part of its lifecycle (onDestroy() etc). Also, retained fragments that have a target were broken. Oops. Change-Id: I5a669b77a2f24b581cde2a0959acf62edb65e326 --- core/java/android/app/Fragment.java | 3 ++ core/java/android/app/FragmentManager.java | 28 ++++++++++++------- .../server/am/ActivityManagerService.java | 10 ++++++- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index f2be9ad9ba3f1..26b3cebdf93df 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -367,6 +367,9 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener // Target fragment. Fragment mTarget; + // For use when retaining a fragment: this is the index of the last mTarget. + int mTargetIndex = -1; + // Target request code. int mTargetRequestCode; diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index f05e2b3b2c579..285f1c1560868 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -695,6 +695,10 @@ final class FragmentManagerImpl extends FragmentManager { if (!f.mAdded && newState > Fragment.CREATED) { newState = Fragment.CREATED; } + if (f.mRemoving && newState > f.mState) { + // While removing a fragment, we can't change it to a higher state. + newState = f.mState; + } if (f.mState < newState) { // For fragments that are created from a layout, when restoring from @@ -915,6 +919,7 @@ final class FragmentManagerImpl extends FragmentManager { // the fragment now should move to once the animation // is done. f.mStateAfterAnimating = newState; + newState = Fragment.CREATED; } else { if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f); if (!f.mRetaining) { @@ -932,9 +937,13 @@ final class FragmentManagerImpl extends FragmentManager { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onDetach()"); } - f.mImmediateActivity = null; - f.mActivity = null; - f.mFragmentManager = null; + if (!f.mRetaining) { + makeInactive(f); + } else { + f.mImmediateActivity = null; + f.mActivity = null; + f.mFragmentManager = null; + } } } } @@ -1040,9 +1049,6 @@ final class FragmentManagerImpl extends FragmentManager { fragment.mRemoving = true; moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED, transition, transitionStyle); - if (inactive) { - makeInactive(fragment); - } } } @@ -1397,6 +1403,7 @@ final class FragmentManagerImpl extends FragmentManager { } fragments.add(f); f.mRetaining = true; + f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1; } } } @@ -1561,6 +1568,7 @@ final class FragmentManagerImpl extends FragmentManager { f.mBackStackNesting = 0; f.mInLayout = false; f.mAdded = false; + f.mTarget = null; if (fs.mSavedFragmentState != null) { fs.mSavedFragmentState.setClassLoader(mActivity.getClassLoader()); f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray( @@ -1600,12 +1608,12 @@ final class FragmentManagerImpl extends FragmentManager { if (nonConfig != null) { for (int i=0; i= 0) { + if (f.mTargetIndex < mActive.size()) { + f.mTarget = mActive.get(f.mTargetIndex); } else { Log.w(TAG, "Re-attaching retained fragment " + f - + " target no longer exists: " + f.mTarget); + + " target no longer exists: " + f.mTargetIndex); f.mTarget = null; } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 1a333ba6d0d52..01bd7a9bd24af 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -7536,7 +7536,8 @@ public final class ActivityManagerService extends ActivityManagerNative pw.println(" COMP_SPEC may also be a component name (com.foo/.myApp),"); pw.println(" a partial substring in a component name, an"); pw.println(" ActivityRecord hex object identifier, or"); - pw.println(" \"all\" for all objects"); + pw.println(" \"all\" for all objects, or"); + pw.println(" \"top\" for the top activity."); pw.println(" -a: include all available server state."); pw.println(" -c: include client state."); return; @@ -8090,6 +8091,13 @@ public final class ActivityManagerService extends ActivityManagerNative activities.add(r1); } } + } else if ("top".equals(name)) { + synchronized (this) { + final int N = mMainStack.mHistory.size(); + if (N > 0) { + activities.add((ActivityRecord)mMainStack.mHistory.get(N-1)); + } + } } else { ComponentName componentName = ComponentName.unflattenFromString(name); int objectId = 0;