mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-02-14 22:37:48 +08:00
Avoid changing back stack when fragment manager is not resumed. (#237)
This change fixes the problem when there are changes being made to the stack while the hosting activity is in paused state (e.g. an activity-based dialog from google play services). In such a case it is not allowed to do any changes which can affect fragment manager's state (e.g. updating backstack). For other changes we use `commitAllowingStatLoss` to indicate we are not interested in fragment manager handling their restoration and hence we can perform most operations. Unfortunately installing back handler is not allowed without state change and we need to wait until the fragment host is resumed before we install it.
This commit is contained in:
committed by
GitHub
parent
0927e03687
commit
cbc86bb6d8
@@ -2,10 +2,10 @@ package com.swmansion.rnscreens;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
@@ -34,6 +34,15 @@ public class ScreenStack extends ScreenContainer<ScreenStackFragment> {
|
||||
}
|
||||
};
|
||||
|
||||
private final FragmentManager.FragmentLifecycleCallbacks mLifecycleCallbacks = new FragmentManager.FragmentLifecycleCallbacks() {
|
||||
@Override
|
||||
public void onFragmentResumed(FragmentManager fm, Fragment f) {
|
||||
if (mTopScreen == f) {
|
||||
setupBackHandlerIfNeeded(mTopScreen);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public ScreenStack(Context context) {
|
||||
super(context);
|
||||
|
||||
@@ -93,12 +102,13 @@ public class ScreenStack extends ScreenContainer<ScreenStackFragment> {
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
FragmentManager fm = getFragmentManager();
|
||||
fm.removeOnBackStackChangedListener(mBackStackListener);
|
||||
getFragmentManager().unregisterFragmentLifecycleCallbacks(mLifecycleCallbacks);
|
||||
if (!fm.isStateSaved()) {
|
||||
// state save means that the container where fragment manager was installed has been unmounted.
|
||||
// This could happen as a result of dismissing nested stack. In such a case we don't need to
|
||||
// reset back stack as it'd result in a crash caused by the fact the fragment manager is no
|
||||
// longer attached.
|
||||
fm.removeOnBackStackChangedListener(mBackStackListener);
|
||||
fm.popBackStack(BACK_STACK_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
}
|
||||
}
|
||||
@@ -106,9 +116,7 @@ public class ScreenStack extends ScreenContainer<ScreenStackFragment> {
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
if (mTopScreen != null) {
|
||||
setupBackHandlerIfNeeded(mTopScreen);
|
||||
}
|
||||
getFragmentManager().registerFragmentLifecycleCallbacks(mLifecycleCallbacks, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,6 +246,12 @@ public class ScreenStack extends ScreenContainer<ScreenStackFragment> {
|
||||
* that case we want the parent navigator or activity handler to take over.
|
||||
*/
|
||||
private void setupBackHandlerIfNeeded(ScreenStackFragment topScreen) {
|
||||
if (!mTopScreen.isResumed()) {
|
||||
// if the top fragment is not in a resumed state, adding back stack transaction would throw.
|
||||
// In such a case we skip installing back handler and use FragmentLifecycleCallbacks to get
|
||||
// notified when it gets resumed so that we can install the handler.
|
||||
return;
|
||||
}
|
||||
getFragmentManager().removeOnBackStackChangedListener(mBackStackListener);
|
||||
getFragmentManager().popBackStack(BACK_STACK_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
ScreenStackFragment firstScreen = null;
|
||||
|
||||
Reference in New Issue
Block a user