ViewPager2套ViewPager2,出现“IllegalArgumentException: Wrong state class...”错误
本文记录了Android开发中ViewPager2嵌套ViewPager2时遇到的"IllegalArgumentException: Wrong state class"错误及解决方案。作者通过分析发现,内层ViewPager2的RecyclerView由系统自动分配ID,在碎片恢复时可能产生ID冲突导致崩溃。解决方案是手动为内层RecyclerView设置固定ID:在Fra
本想继续前进,但是担心忘了无处寻找,又不忍后来者如我曾经一样无助、苦闷,便强压住“狂躁”的心,将爬坑的结果记录下来,以备忘,以交流。
Android开发中,ViewPager2中套ViewPager2,以实现丰富的展示效果。但我在实现的过程中遇到了如下错误提示。
一、错误场景
碎片一:其中含“外层”ViewPager2对象:vp1
public class FragmentOne extends Fragment {
private ViewPager2 vp1;
...
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
vp1 = view.findViewById(R.id.vp1); // 右侧viewPager2
vp1.setAdapter(new FragmentStateAdapter(getChildFragmentManager(), getLifecycle()) {
...
@Override
public Fragment createFragment(int position) {
Fragment fragment = FragmentOne.newInstance(id, name);
return fragment;
}
});
}
...
}
碎片二:其中含“内层”ViewPager2对象:vp2
public class FragmentTwo extends Fragment {
...
public static Fragment newInstance(String id, name) {
...
return fragment;
}
...
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
vp2 = view.findViewById(R.id.vp2);
vp2.setAdapter(new FragmentStateAdapter(getChildFragmentManager(), getLifecycle()) {
...
});
}
...
}
“碎片一”处于一个元素较少的集合中,如屏幕底端的“首页、分类、购物车、我的”中的“分类”标题对应碎片;“碎片二”处于一个元素较多的集合中,如分类中的某一大类。碎片二“长在”碎片一中的ViewPager2中,“碎片二”中的ViewPager2管理着大量碎片(某个大分类下更小的分类)。
运行之后提示错误:IllegalArgumentException: Wrong state class…
二、错误分析
起初以为自己代码错误,经过反复测试、诊断,无法解决问题,后经网上搜索,逐渐“似懂非懂”地明白了一些:
ViewPager2 使用 RecyclerView 作为其内部实现,内层的ViewPager2中的RecyclerView,我们并没有手动赋予其id,而是由系统赋予。由于ViewPager2的碎片加载机制,外层ViewPager2 管理的碎片中,离当前显示的碎片远的碎片可能会被销毁,但再恢复这个碎片时,其内层ViewPager2的RecyclerView的系统赋予的id可能会导致“id重复”,恢复出错。
本例中“碎片一”中的ViewPager2欲恢复刚刚销毁的某“碎片二”对象,但由于“碎片二”中管理其下级碎片的ViewPager2中的RecyclerView的id,由系统赋予,造成返回给上级ViewPager2的视图的id与已有的某个id相同,恢复失败,系统崩溃。
解决思路之一就是:为内层ViewPager2中的 RecyclerView手动赋id。
三、解决办法
在“碎片二”中,找出ViewPager2的对象vp2中的RecyclerView并为其赋id,代码如下:
public class FragmentTwo extends Fragment {
...
public static Fragment newInstance(String id, name) {
...
return fragment;
}
...
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
vp2 = view.findViewById(R.id.vp2);
// 以下if代码通过修改RecyclerView的id的方法防止ViewPager2出现
// “java.lang.IllegalArgumentException: Wrong state class...”错误
if (vp2 != null) {
View child;
int len = vp2.getChildCount();
for (int i = 0; i < len; i++) {
child = vp2.getChildAt(i);
if (child instanceof RecyclerView) {
// 只是一个id,无视图布局
child.setId(R.id.general_inner_recycler);
break;
}
}
}
vp2.setAdapter(new FragmentStateAdapter(getChildFragmentManager(), getLifecycle()) {
...
});
}
...
}
其中一行代码:child.setId(R.id.general_inner_recycler);中的“general_inner_recycler”是手动输入的一个id,此时系统中并未有此id,general_inner_recycler会变红,可以鼠标指向该变红字体,根据跳出的“提示”操作即可。提示大意是在资源文件中创建values夹,并创建ids.xml文件,将这个id存入该文件。这样省去了手动创建的麻烦 ,创建后形如:
四、总结
其实,不只是ViewPager2中嵌套ViewPager2,但凡恢复含有ViewPager2的对象时,都有可能出现“IllegalArgumentException: Wrong state class…”错误,其处理方法也不止修改RecyclerView的id一种,应根据实际情况加以应对。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)