package com.example.modifier; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.View; import androidx.annotation.IdRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import androidx.navigation.NavDestination; import androidx.navigation.NavOptions; import androidx.navigation.Navigator; import androidx.navigation.fragment.FragmentNavigator; import java.lang.reflect.Field; import java.util.ArrayDeque; import java.util.List; import java.util.Map; @Navigator.Name("fixFragment") public class FixFragmentNavigator extends FragmentNavigator { private final String TAG = "ReLoadFragmentNavictor"; private final Context mContext; private final FragmentManager mFragmentManager; private final int mContainerId; String oldClassName = null; public FixFragmentNavigator(@NonNull Context context, @NonNull FragmentManager manager, int containerId) { super(context, manager, containerId); mContext = context; mFragmentManager = manager; mContainerId = containerId; } @Nullable @Override public NavDestination navigate(@NonNull 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.equals(oldClassName)) { return null; } oldClassName = className; if (className.charAt(0) == '.') { className = mContext.getPackageName() + className; } Fragment frag = mFragmentManager.findFragmentByTag(className); if (null == frag) { //不存在,则创建 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); } // ft.replace(mContainerId, frag); List fragments = mFragmentManager.getFragments(); for (Fragment fragment : fragments) { ft.hide(fragment); } if (!frag.isAdded()) { ft.add(mContainerId, frag, className); } ft.show(frag); ft.setPrimaryNavigationFragment(frag); final @IdRes int destId = destination.getId(); //通过反射获取mBackStack ArrayDeque mBackStack; try { Field field = FragmentNavigator.class.getDeclaredField("mBackStack"); field.setAccessible(true); mBackStack = (ArrayDeque) field.get(this); } catch (Exception e) { e.printStackTrace(); return null; } final boolean initialNavigation = mBackStack.isEmpty(); final boolean isSingleTopReplacement = navOptions != null && !initialNavigation && navOptions.shouldLaunchSingleTop() && mBackStack.peekLast() == destId; boolean isAdded; if (initialNavigation) { isAdded = true; } else if (isSingleTopReplacement) { if (mBackStack.size() > 1) { 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 Extras) { Extras extras = (Extras) navigatorExtras; for (Map.Entry sharedElement : extras.getSharedElements().entrySet()) { ft.addSharedElement(sharedElement.getKey(), sharedElement.getValue()); } } ft.setReorderingAllowed(true); ft.commit(); if (isAdded) { mBackStack.add(destId); return destination; } else { return null; } } //navigate需要打方法重复类直接复制过来就可以 @NonNull private String generateBackStackName(int backStackIndex, int destId) { return backStackIndex + "-" + destId; } }