java - java.lang.IllegalStateException:当我有一个 BottomNavigationBar 时已经添加了片段 - 可能是片段的多个实例
问题描述
这很复杂,但是我的应用程序中有一个部分(“运行”部分),它的底部导航栏有 4 个图标/片段。当我第一次“运行”时,一切正常。当我第二次“运行”时,只要单击导航栏主/默认(或第一个)片段中列出的回收视图中的一个项目,应用程序就会崩溃。我收到的错误是:
java.lang.IllegalStateException: Fragment already added
我认为其中一个复杂性是应用程序的“运行”部分是一个片段,其中包含 BottomNavigationView。所有的例子似乎在活动中都有这个。
我已经读过这可能是一个一般性错误,但我确实注意到在主/默认片段中单击 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.
底部导航栏中的代码如下,根据so中的其他示例,这似乎是合理的:
private void switchFragment(Fragment fragment) {
FragmentManager fm = getActivity().getSupportFragmentManager();
fm.beginTransaction().replace(R.id.frame_layout_run_scenario, fragment).addToBackStack(null).commit();
}
是否正在创建同一片段的多个实例?我不知道这怎么可能发生。我想它一定是在我创建带有 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 被多次调用。
我的错。感谢您的帮助。
解决方案
在您的片段类中声明片段如下
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();
推荐阅读
- javascript - 多功能 onClick javascript
- python - Python:通过函数构造类(和变量名)?
- reactjs - react-pdf/renderer Image 组件破坏了整个文件中的样式
- python-3.x - Python 3:为什么这种方法在已经工作后不将变量除以熊猫数据框的索引?
- javascript - 在Javascript中组合字典中的数组
- powershell - Power shell 复制项目以递归方式搜索选定文件并将仅文件复制到目标文件夹
- c++ - c++ std::map `emplace` 和 `emplace_back` 重载
- javascript - Date-fns 返回不正确的日期
- angular - Angular Material 选项卡 - 新添加的选项卡是半隐藏的
- templates - 编译时的 C++ 接口声明?