Ensure exit effects run when using max lifecycle CREATED
Fragments should always wait for their exit effects
to run before moving down to CREATED, whether that
is because they are detached, being removed, or via
setMaxLifecycle(CREATED). By moving the logic for
the max lifecycle earlier in computeExpectedState(),
we ensure the LifecycleImpact.REMOVING code will
take precedence.
Test: updated FragmentLifecycleTest passes
BUG: 165822335
Change-Id: I55d96519f202af12379bdd27c87638004ffa3298
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentLifecycleTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentLifecycleTest.kt
index d9dd33d..28cc10b 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentLifecycleTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentLifecycleTest.kt
@@ -287,12 +287,16 @@
.commitNow()
assertThat(fragment.lifecycle.currentState).isEqualTo(Lifecycle.State.RESUMED)
+ val view = fragment.requireView()
+ assertThat(view.parent).isNotNull()
fm.beginTransaction()
.setMaxLifecycle(fragment, Lifecycle.State.CREATED)
.commitNow()
assertThat(fragment.lifecycle.currentState).isEqualTo(Lifecycle.State.CREATED)
+ assertThat(fragment.view).isNull()
+ assertThat(view.parent).isNull()
}
@Test
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
index 00c1d0b..2ea46d2 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentStateManager.java
@@ -176,6 +176,24 @@
// Assume the Fragment can go as high as the FragmentManager's state
int maxState = mFragmentManagerState;
+ // Don't allow the Fragment to go above its max lifecycle state
+ switch (mFragment.mMaxState) {
+ case RESUMED:
+ // maxState can't go any higher than RESUMED, so there's nothing to do here
+ break;
+ case STARTED:
+ maxState = Math.min(maxState, Fragment.STARTED);
+ break;
+ case CREATED:
+ maxState = Math.min(maxState, Fragment.CREATED);
+ break;
+ case INITIALIZED:
+ maxState = Math.min(maxState, Fragment.ATTACHED);
+ break;
+ default:
+ maxState = Math.min(maxState, Fragment.INITIALIZING);
+ }
+
// For fragments that are created from a layout using the <fragment> tag (mFromLayout)
if (mFragment.mFromLayout) {
if (mFragment.mInLayout) {
@@ -227,23 +245,6 @@
if (mFragment.mDeferStart && mFragment.mState < Fragment.STARTED) {
maxState = Math.min(maxState, Fragment.ACTIVITY_CREATED);
}
- // Don't allow the Fragment to go above its max lifecycle state
- switch (mFragment.mMaxState) {
- case RESUMED:
- // maxState can't go any higher than RESUMED, so there's nothing to do here
- break;
- case STARTED:
- maxState = Math.min(maxState, Fragment.STARTED);
- break;
- case CREATED:
- maxState = Math.min(maxState, Fragment.CREATED);
- break;
- case INITIALIZED:
- maxState = Math.min(maxState, Fragment.ATTACHED);
- break;
- default:
- maxState = Math.min(maxState, Fragment.INITIALIZING);
- }
return maxState;
}