解决方案先放最前面:找到覆写的FragmentNavigator类中public NavDestination navigate(@NonNull FragmentNavigator.Destination destination, @Nullable Bundle args, @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras)这个方法,添加ft.setMaxLifecycle(lastFragment, Lifecycle.State.STARTED);如下面代码所示
if (mFragmentManager.getFragments().size() > 0) {
Fragment lastFragment = mFragmentManager.getFragments().get(mFragmentManager.getFragments().size() - 1);
ft.hide(lastFragment);
//添加这行,保证fragment生命周期回调
ft.setMaxLifecycle(lastFragment, Lifecycle.State.STARTED);
if (frag.isAdded()) {
ft.show(frag);
} else {
ft.add(mContainerId, frag);
}
} else {
ft.replace(mContainerId, frag);
}
// ft.replace(mContainerId, frag);
ft.setPrimaryNavigationFragment(frag);
Navigation库版本:2.3.2
有经验的开发者看见这个肯定知道这就是AndroidX下FragmentManager切换的生命周期设置方法。
最近开发的新项目使用了Navigation导航做单Activity应用,一开始被Navigation的replace切换fragment方式困扰,找到方法换成了show/hide方式,后续的开发阶段中又发现需要在生命周期回调中做些事情,之前的代码中返回上一级fragment时没有按照预期回调onResume,经过思考后(其实就是想起来以前做首页底部导航时的做法)找到了如上的解决方案,运行结果如下
最后附送找到的使用show/hide方式替换replace的fragment解决返回上一级全部重新走fragment生命周期困扰的方式,感谢广大网友。
1.复制androidx.navigation:navigation-fragment包中的FragmentNavigator类内容,找到下面的方法添加修改内容;
2.复制NavHostFragment类,将其中的FragmentNavigator类替换成上一步修改的FragmentNavigator类;
3.在使用导航的xml布局中把原本的NavHostFragment替换成我们修改后的NavHostFragment类。
@Nullable
@Override
public NavDestination navigate(@NonNull FragmentNavigator.Destination destination, @Nullable Bundle args,
@Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) {
if (mFragmentManager.isStateSaved()) {
Log.i(TAG, "Ignoring navigate() call: FragmentManager has already saved its state");
return null;
}
String className = destination.getClassName();
if (className.charAt(0) == '.') {
className = mContext.getPackageName() + className;
}
final Fragment frag = instantiateFragment(mContext, mFragmentManager, className, args);
frag.setArguments(args);
final FragmentTransaction ft = mFragmentManager.beginTransaction();
int enterAnim = navOptions != null ? navOptions.getEnterAnim() : -1;
int exitAnim = navOptions != null ? navOptions.getExitAnim() : -1;
int popEnterAnim = navOptions != null ? navOptions.getPopEnterAnim() : -1;
int popExitAnim = navOptions != null ? navOptions.getPopExitAnim() : -1;
if (enterAnim != -1 || exitAnim != -1 || popEnterAnim != -1 || popExitAnim != -1) {
enterAnim = enterAnim != -1 ? enterAnim : 0;
exitAnim = exitAnim != -1 ? exitAnim : 0;
popEnterAnim = popEnterAnim != -1 ? popEnterAnim : 0;
popExitAnim = popExitAnim != -1 ? popExitAnim : 0;
ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim);
}
//-------------------修改的内容开始------------------------------------
if (mFragmentManager.getFragments().size() > 0) {
Fragment lastFragment = mFragmentManager.getFragments().get(mFragmentManager.getFragments().size() - 1);
ft.hide(lastFragment);
ft.setMaxLifecycle(lastFragment, Lifecycle.State.STARTED);
if (frag.isAdded()) {
ft.show(frag);
} else {
ft.add(mContainerId, frag);
}
} else {
ft.replace(mContainerId, frag);
}
// ft.replace(mContainerId, frag);
ft.setPrimaryNavigationFragment(frag);
//--------------------修改内容结束---------------------------------------
final @IdRes int destId = destination.getId();
final boolean initialNavigation = mBackStack.isEmpty();
// TODO Build first class singleTop behavior for fragments
final boolean isSingleTopReplacement = navOptions != null && !initialNavigation
&& navOptions.shouldLaunchSingleTop()
&& mBackStack.peekLast() == destId;
boolean isAdded;
if (initialNavigation) {
isAdded = true;
} else if (isSingleTopReplacement) {
// Single Top means we only want one instance on the back stack
if (mBackStack.size() > 1) {
// If the Fragment to be replaced is on the FragmentManager's
// back stack, a simple replace() isn't enough so we
// remove it from the back stack and put our replacement
// on the back stack in its place
mFragmentManager.popBackStack(
generateBackStackName(mBackStack.size(), mBackStack.peekLast()),
FragmentManager.POP_BACK_STACK_INCLUSIVE);
ft.addToBackStack(generateBackStackName(mBackStack.size(), destId));
}
isAdded = false;
} else {
ft.addToBackStack(generateBackStackName(mBackStack.size() + 1, destId));
isAdded = true;
}
if (navigatorExtras instanceof FragmentNavigator.Extras) {
FragmentNavigator.Extras extras = (FragmentNavigator.Extras) navigatorExtras;
for (Map.Entry<View, String> sharedElement : extras.getSharedElements().entrySet()) {
ft.addSharedElement(sharedElement.getKey(), sharedElement.getValue());
}
}
ft.setReorderingAllowed(true);
ft.commit();
// The commit succeeded, update our view of the world
if (isAdded) {
mBackStack.add(destId);
return destination;
} else {
return null;
}
}