ViewPager2通过混淆FragmentStateAdapter的两个实例导致崩溃

问题描述

我在我的应用程序中使用ViewPager2TabLayout一个片段(我们称它为主要片段)。这些页面本身就是片段,每个片段都按格式表示音乐项目列表,例如CD的页面,乙烯基的页面等。FragmentStateAdapter包含通过观察LiveData对象而更新的格式的列表。

我为用户添加一个DialogFragment添加格式(即页面)的选项,这在某些情况下会使应用程序崩溃。如果在用户打开音乐项目时使用它-从而使主片段经过onPause,onStop等生命周期阶段-然后返回主片段,然后再次打开音乐项目并添加新的格式,应用程序崩溃,并且日志记录程序表明发生了这种情况,因为虽然它从最近更新的FragmentStateAdapter获取选项卡/页面数,但其自身经历的格式列表来自{{1 }}以前的生命周期。因此,当用于设置标签页文本的FragmentStateAdapter回调击中TabLayoutMediator时,应用程序崩溃。

我希望我已经足够清楚地解释了这个问题。 如果有任何遗漏,请告诉我。

以下是相关代码

indexoutofboundsexception

解决方法

最终我自己弄清楚了。问题是我观察到了适配器构造函数中的格式LiveData。这使得notifyDataSetChanged()方法可以通知适配器的确切实例。但是ViewPager已从onViewCreated中新构建的适配器中获取了页数。通过将LiveData观察者移动到onViewCreated,并通知当前与ViewPager关联的适配器来解决此问题:

 mViewModel = new ViewModelProvider(this).get(UserItemsViewModel.class);
        viewPager.setAdapter(new ItemListFragmentAdapter(requireActivity(),mType));
        new TabLayoutMediator(tabLayout,viewPager,(tab,position) -> {

                    if (position == 0) {
                        tab.setText("All");
                    } else {
                        tab.setText(((ItemListFragmentAdapter) viewPager.getAdapter()).getItemAt(position - 1).getName());
                    }
                }
        ).attach();

        mViewModel.getFormatsLD().observe(getViewLifecycleOwner(),new Observer<List<FormatItem>>() {
            @Override
            public void onChanged(List<FormatItem> formatItems) {
                ItemListFragmentAdapter adapter = (ItemListFragmentAdapter) viewPager.getAdapter();
                if (adapter != null) {
                    ((ItemListFragmentAdapter) viewPager.getAdapter()).setItems(formatItems);
                    adapter.notifyDataSetChanged();
                }
            }
        });