问题描述
我在我的应用程序中使用ViewPager2
和TabLayout
的一个片段(我们称它为主要片段)。这些页面本身就是片段,每个片段都按格式表示音乐项目列表,例如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();
}
}
});