【发布时间】:2020-09-11 16:45:20
【问题描述】:
我在我的应用程序中的片段中使用ViewPager2 和TabLayout(我们称其为主要片段)。这些页面本身就是片段,每个都按格式表示音乐项目列表,例如CD 页面、黑胶唱片页面等。FragmentStateAdapter 包含通过观察LiveData 对象更新的格式列表。
我为用户添加了一个选项,可以在 DialogFragment 中添加格式(即页面),这会在某些情况下使应用程序崩溃。如果在用户打开音乐项目时使用它——从而让主片段经历 onPause、onStop 等生命周期阶段——然后返回主片段,再次打开音乐项目并添加新的格式,应用程序崩溃,并且 logcat 显示这是因为 虽然它从最近更新的FragmentStateAdapter 获取选项卡/页面的数量,但它所经历的格式列表本身来自以前的 FragmentStateAdapter生命周期。因此,当用于设置标签文本的TabLayoutMediator 回调遇到IndexOutOfBoundsException 时,应用会崩溃。
我希望我已经设法足够清楚地解释了这个问题。 如果有任何遗漏,请告诉我。
以下是相关代码:
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Log.d(TAG, "onViewCreated called");
viewPager = view.findViewById(R.id.view_pager);
tabLayout = view.findViewById(R.id.tab_layout);
mViewModel = new ViewModelProvider(this).get(UserItemsViewModel.class);
viewPager.setAdapter(new ItemListFragmentAdapter(requireActivity(), mType));
new TabLayoutMediator(tabLayout, viewPager,
(tab, position) -> {
// Log.d(TAG, "position: " + position);
// Log.d(TAG, String.valueOf(listFragmentAdapter.mItems));
if (position == 0) {
tab.setText("All");
} else {
// Log.d(TAG, "position: " + position);
// Log.d(TAG, "onActivityCreated: " + listFragmentAdapter);
tab.setText(((ItemListFragmentAdapter)viewPager.getAdapter()).getItemAt(position - 1).getName());
}
}
).attach();
}
class ItemListFragmentAdapter extends FragmentStateAdapter {
// private static final String TAG = ItemListFragmentAdapter.class.getSimpleName();
private final String mType;
private AtomicReference<List<FormatItem>> mItems;
ItemListFragmentAdapter(FragmentActivity activity, String type) {
super(activity);
mType = type;
mItems = new AtomicReference<>();
mViewModel.getFormatsLD().observe(activity, new Observer<List<FormatItem>>() {
@Override
public void onChanged(List<FormatItem> formatItems) {
mItems.set(formatItems);
notifyDataSetChanged();
}
});
}
@NonNull
@Override
public Fragment createFragment(int position) {
Log.d(TAG, "createFragment called");
if (mType.equals(ARG_COLLECTION)) {
return CollectionFragment.newInstance(position);
} else if (mType.equals(ARG_WISHLIST)) {
return WishlistFragment.newInstance(position);
} else {
throw new IllegalArgumentException();
}
}
@Override
public int getItemCount() {
Log.d(TAG, "getItemCount: " + this);
if(mItems.get() != null){
Log.d(TAG, "getItemCount: size - " + mItems.get().size());
}
return mItems.get() == null ? 1 : mItems.get().size() + 1;
}
FormatItem getItemAt(int i){
Log.d(TAG, "i: " + i);
Log.d(TAG, "size: " + mItems.get().size());
Log.d(TAG, "list: " + mItems.get());
Log.d(TAG, "getItemAt: " + this);
return mItems.get() == null ? null : mItems.get().get(i);
}
}
【问题讨论】:
标签: android android-tablayout android-viewpager2