java.lang.IllegalStateException: 当我有一个 BottomNavigationBar 时片段已经添加 - 可能片段的多个实例

java.lang.IllegalStateException: Fragment already added when I have a BottomNavigationBar - maybe multiple instances of fragment

这很复杂,但是,我的应用程序中有一个部分(“运行”部分),它有一个带有 4 icons/fragments 的底部导航栏。当我第一次“运行”时一切正常。当我第二次“运行”时,只要单击导航栏的 main/default(或第一个)片段中列出的回收视图中的一个项目,应用程序就会崩溃。我收到的错误是:

java.lang.IllegalStateException: Fragment already added

我认为复杂性之一是应用程序的“运行”部分是一个片段,其中包含 BottomNavigationView。所有示例似乎都在 activity.

我读过这可能是一个一般性错误,但我确实注意到在 main/default 片段中单击 recyclerview 项目时出现的日志消息似乎是重复的,就好像有多个实例一样:

第一个运行:

2021-07-29 07:51:37.996  D/RunScenarioFragment: showDialog: dialog is null
2021-07-29 07:51:37.996  D/RunScenarioFragment: showDialog: creating new dialog

第二个运行:

2021-07-29 07:53:04.565  D/RunScenarioFragment: showDialog: dialog is null
2021-07-29 07:53:04.565  D/RunScenarioFragment: showDialog: creating new dialog
2021-07-29 07:53:04.575  D/RunScenarioFragment: showDialog: dialog is NOT null
2021-07-29 07:53:04.575  D/RunScenarioFragment: showDialog: no need to create new dialog.
2021-07-29 07:53:04.580  D/RunScenarioFragment: showDialog: dialog is NOT null
2021-07-29 07:53:04.580  D/RunScenarioFragment: showDialog: no need to create new dialog.

bottomnavigationbar中的代码如下,根据中的so似乎是合理的:

private void switchFragment(Fragment fragment) {
    FragmentManager fm = getActivity().getSupportFragmentManager();
    fm.beginTransaction().replace(R.id.frame_layout_run_scenario, fragment).addToBackStack(null).commit();
}

是否正在创建同一片段的多个实例?我不知道怎么会这样。我想一定是在我创建片段 w/the BottomNavigationBar 时,但这实际上只是一个导航调用。也许当我退出但又一次我只是导航离开:

navController.navigate(R.id.action_global_scenarioListFragment2);

这是我的听众:

bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {

            Fragment selectedFragment;

            switch (menuItem.getItemId()) {
                case R.id.runScenarioDashboardFragment:   //nav_scenario_run_home
                    selectedFragment = new RunScenarioDashboardFragment();
                    break;
                case R.id.runScenarioLogFragment:       //nav_scenario_run_log
                    selectedFragment = new RunScenarioLogFragment();
                    break;
                case R.id.runScenarioCommunicationFragment:     //communication fragment

                    selectedFragment = new RunScenarioCommunicationFragment();
                    break;
                default:
                    selectedFragment = new RunScenarioTokenFragment();
                    break;
            }

            switchFragment(selectedFragment);
            return true;
        }
    });

更新 它似乎与我正在调用的自定义 AppCompatDialogFragment 有关。

我的底部导航代码工作正常。不是这部分代码导致了问题。是 AppCompatDialogFragment 被多次调用。

我的错。谢谢你的帮助。

在你的片段中class声明片段如下

RunScenarioDashboardFragment runScenarioDashboardFragment;
RunScenarioLogFragment runScenarioLogFragment;
RunScenarioCommunicationFragment runScenarioCommunicationFragment;
RunScenarioTokenFragment runScenarioTokenFragment

@Override
    public void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        runScenarioDashboardFragment = new RunScenarioDashboardFragment();
        runScenarioLogFragment = new RunScenarioLogFragment();
        runScenarioCommunicationFragment = new RunScenarioCommunicationFragment();
        runScenarioTokenFragment = new RunScenarioTokenFragment();

    }

@Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        // your onCreateView implementation
    }

将您的导航侦听器更新为

bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        Fragment selectedFragment=null;

        switch (menuItem.getItemId()) {
            case R.id.runScenarioDashboardFragment:   //nav_scenario_run_home
                selectedFragment = runScenarioDashboardFragment;
                break;
            case R.id.runScenarioLogFragment:       //nav_scenario_run_log
                selectedFragment = runScenarioLogFragment;
                break;
            case R.id.runScenarioCommunicationFragment:     //communication fragment

                selectedFragment = runScenarioCommunicationFragment;
                break;
            default:
                selectedFragment = runScenarioTokenFragment;
                break;
        }

        switchFragment(selectedFragment);
        return true;
    }
});

同时更新你的 switchFragment()

private void switchFragment(Fragment fragment) {
    FragmentManager fm = getActivity().getSupportFragmentManager();
    
    // this will popout the fragment in back stack if it was there and then 
    // begin the new transaction, add following code only if you add fragment to back stack
    if(getSupportFragmentManager().getBackStackEntryCount()>0)
        getSupportFragmentManager()..popBackStack();

    fm.beginTransaction().replace(R.id.frame_layout_run_scenario, fragment).addToBackStack(null).commit();
}

或者干脆不在后台栈中添加

fm.beginTransaction().replace(R.id.frame_layout_run_scenario,    fragment).commit();

不是上面的代码。这是按预期工作的。这是对导致问题的 AppCompatDialogFragment 的多次调用。上面的代码适用于 BottomNavigationView。

谢谢大家的帮助。