From f804d6ade78bb42a7f4a101510f041bd6ca26eeb Mon Sep 17 00:00:00 2001 From: George Mount Date: Wed, 5 Apr 2017 12:30:17 -0700 Subject: [PATCH] Save FragmentManagerNonConfig during onSaveInstanceState() Bug 36815706 onSaveInstanceState() is called prior to onStop(), but onRetainNonConfigInstance() is called after. When a retained instance fragment is added during onStop(), the state of the two configurations won't match. This CL moves the non-configuration save to happen immediately after the save instance state. Support Lib Change: Ib41cbe02d060d3411e32d1494525e119d0c23dd7 Test: I30e598abf7faceac3294aef1ee0ee3b07d3aa7c6 Change-Id: I861629e2c6da2d8b0e075e8283b631fdf80670c0 --- core/java/android/app/FragmentManager.java | 44 ++++++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 3107453b9023b..6460cb5c17f1e 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -695,6 +695,9 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate // This is dangerous, but we want to keep from breaking old applications. boolean mAllowOldReentrantBehavior; + // Saved FragmentManagerNonConfig during saveAllState() and cleared in noteStateNotSaved() + FragmentManagerNonConfig mSavedNonConfig; + Runnable mExecCommit = new Runnable() { @Override public void run() { @@ -2518,6 +2521,35 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } FragmentManagerNonConfig retainNonConfig() { + setRetaining(mSavedNonConfig); + return mSavedNonConfig; + } + + /** + * Recurse the FragmentManagerNonConfig fragments and set the mRetaining to true. This + * was previously done while saving the non-config state, but that has been moved to + * {@link #saveNonConfig()} called from {@link #saveAllState()}. If mRetaining is set too + * early, the fragment won't be destroyed when the FragmentManager is destroyed. + */ + private static void setRetaining(FragmentManagerNonConfig nonConfig) { + if (nonConfig == null) { + return; + } + List fragments = nonConfig.getFragments(); + if (fragments != null) { + for (Fragment fragment : fragments) { + fragment.mRetaining = true; + } + } + List children = nonConfig.getChildNonConfigs(); + if (children != null) { + for (FragmentManagerNonConfig child : children) { + setRetaining(child); + } + } + } + + void saveNonConfig() { ArrayList fragments = null; ArrayList childFragments = null; if (mActive != null) { @@ -2529,13 +2561,13 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate fragments = new ArrayList<>(); } fragments.add(f); - f.mRetaining = true; f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1; if (DEBUG) Log.v(TAG, "retainNonConfig: keeping retained " + f); } boolean addedChild = false; if (f.mChildFragmentManager != null) { - FragmentManagerNonConfig child = f.mChildFragmentManager.retainNonConfig(); + f.mChildFragmentManager.saveNonConfig(); + FragmentManagerNonConfig child = f.mChildFragmentManager.mSavedNonConfig; if (child != null) { if (childFragments == null) { childFragments = new ArrayList<>(); @@ -2554,9 +2586,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } } if (fragments == null && childFragments == null) { - return null; + mSavedNonConfig = null; + } else { + mSavedNonConfig = new FragmentManagerNonConfig(fragments, childFragments); } - return new FragmentManagerNonConfig(fragments, childFragments); } void saveFragmentViewState(Fragment f) { @@ -2617,6 +2650,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate execPendingActions(); mStateSaved = true; + mSavedNonConfig = null; if (mActive == null || mActive.size() <= 0) { return null; @@ -2717,6 +2751,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate if (mPrimaryNav != null) { fms.mPrimaryNavActiveIndex = mPrimaryNav.mIndex; } + saveNonConfig(); return fms; } @@ -2892,6 +2927,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } public void noteStateNotSaved() { + mSavedNonConfig = null; mStateSaved = false; final int addedCount = mAdded == null ? 0 : mAdded.size(); for (int i = 0; i < addedCount; i++) {