请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

自定义的NavHostFragment报错

老师好,我按照老师的思路重新了NavHostFragment和FragmentNavigator然后在xml中导入自定义NavHostFragment,结果程序直接崩溃了,找不到问题,求老师帮我看看。

public class FixFragmentNavigator extends FragmentNavigator {
    private static final String TAG ="FixNavigator" ;
    private FragmentManager mFragmentManager;
    private Context mContext;
    private int mContainerId;

    public FixFragmentNavigator(@NonNull Context context, @NonNull FragmentManager manager, int containerId) {
        super(context, manager, containerId);
        mFragmentManager=manager;
        mContext=context;
        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.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);
        }

        //这里修改replace为hide和show
        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.setPrimaryNavigationFragment(frag);

        ArrayDeque<Integer> mBackStack = new ArrayDeque<>();
        final @IdRes int destId = destination.getId();
        try {
            Field field = FragmentNavigator.class.getDeclaredField("mBackStack");
            field.setAccessible(true);
            mBackStack = (ArrayDeque<Integer>)field.get(this);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }

        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 Extras) {
            Extras extras = (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;
        }
    }

    private String generateBackStackName(int backStackIndex,int destId){
        return backStackIndex+"-"+destId;
    }
}

public class FixNavHostFragment extends NavHostFragment {

@NonNull
@Override
protected Navigator<? extends FragmentNavigator.Destination> createFragmentNavigator(){
    Class clazz=NavHostFragment.class;
    int id=0;
    try {
        NavHostFragment hostFragment=(NavHostFragment) clazz.newInstance();
        Method getContainerId=clazz.getMethod("getContainerId");
        id=(int)getContainerId.invoke(hostFragment);
    } catch (IllegalAccessException  | InvocationTargetException | NoSuchMethodException e) {
        e.printStackTrace();
    } catch (java.lang.InstantiationException e) {
        e.printStackTrace();
    }
    return new FixFragmentNavigator(requireContext(), getChildFragmentManager(), id);
}

}

正在回答

1回答

报错日志贴出来看看,根据报错日志找报错的代码,从而解决它

0 回复 有任何疑惑可以回复我~
  • 提问者 慕勒6194056 #1
    老师好,报错日志如下:
    Caused by: java.lang.IllegalStateException: Could not find Navigator with name "fragment". You must call NavController.addNavigator() for each navigation type.
    我开的是新项目,其他地方未改动,
    
    自定义的fragmentNavigator有加@Navigator.Name("FixFragmentNavigator")注解
    回复 有任何疑惑可以回复我~ 2021-08-13 09:26:21
  • 它的报错也很清晰啊,You must call NavController.addNavigator() for each navigation type.
    
    没有吧自定义的navigator添加到navController中
    
    你把课程源码下下来,对比下。课程中特地讲了这一点的
    回复 有任何疑惑可以回复我~ 2021-08-13 10:11:02
  • 提问者 慕勒6194056 回复 LovelyChubby #3
    解决了,加了navController.navigatorProvider += navigator就行了,之前找add方法找不到,谢谢老师
    回复 有任何疑惑可以回复我~ 2021-08-13 10:23:43
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信