Android RecyclerView滚动时动态添加的视图不受控重复错乱问题
重复视图问题根因
RecyclerView采用ViewHolder 视图复用机制:滑出屏幕的列表项不会被销毁,会被放入缓存池供后续新位置绑定复用。
当前代码存在三个核心问题直接导致异常:
onBindViewHolder方法没有在绑定时清理容器上残留的旧动态视图,每次绑定都直接往LinearLayout上追加新视图,滚动次数越多,叠加的重复视图数量就越多- 复用机制下,原本绑定其他题型的ViewHolder被重新用于新题型时,旧题型动态添加的视图没有被移除,会直接混在新题型的视图里,造成不同题目的视图串位、顺序错乱
- 代码中插入的
setHasTransientState调用是完全冗余的操作,对解决重复问题没有任何帮助,反而可能干扰RecyclerView的正常复用逻辑
修复方案
核心逻辑说明
核心清理逻辑:在每次绑定视图的最开始,清空动态添加的残留视图,再根据当前题目类型生成对应内容。
注意:你的根LinearLayout第一个子元素是固定展示题目的txtQuizTextView,清理时不能直接调用removeAllViews()删掉题目标题,只需要保留索引为0的标题视图,删除后续所有动态添加的子视图即可。
优化后完整代码
修改onBindViewHolder方法,在最开头加入清理逻辑,移除所有冗余的setHasTransientState调用:
@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { Quiz quiz = quizzes.get(position); // 绑定固定题目标题 holder.tvQuiz.setText(quiz.getQuiz()); LinearLayout linearLayout = holder.linearLayout; // 核心清理逻辑:保留第一个固定的题目标题,删除所有残留的动态视图 while (linearLayout.getChildCount() > 1) { linearLayout.removeViewAt(1); } // 按题型动态生成对应视图 if (quiz instanceof QuizType0) { RadioGroup radioGroup = new RadioGroup(linearLayout.getContext()); radioGroup.setOrientation(RadioGroup.VERTICAL); for (String option : ((QuizType0) quiz).getOptionsList()) { RadioButton radioButton = new RadioButton(linearLayout.getContext()); radioButton.setText(option); radioGroup.addView(radioButton); } linearLayout.addView(radioGroup); } if (quiz instanceof QuizType1) { for (String option : ((QuizType1) quiz).getOptionsList()) { CheckBox checkBox = new CheckBox(linearLayout.getContext()); checkBox.setText(option); linearLayout.addView(checkBox); } } if (quiz instanceof QuizType2) { EditText editText = new EditText(linearLayout.getContext()); linearLayout.addView(editText); } }
长期优化建议
- 调整单个题目的布局结构:在原有静态题目标题TextView下方,单独新增一个id为
ll_dynamic_container的空LinearLayout作为动态内容容器。后续清理时直接对这个空容器执行removeAllViews(),不用手动判断保留哪个子视图,逻辑更简洁也不容易出错 - 为不同题型设置独立的ViewType:重写Adapter的
getItemViewType方法,根据题目类型返回不同的类型标识,让RecyclerView为不同题型创建对应的ViewHolder,从根源上避免不同题型的视图复用串位,同时提升列表滚动性能 - 做好用户作答状态的同步:RecyclerView视图复用时,控件上保存的用户选择、输入内容会随视图被复用给其他题目。需要在视图的回收回调(
onViewRecycled)中,把控件上的用户操作值同步更新到对应的Quiz实体类中,避免滚动后作答内容丢失或者串题
内容的提问来源于stack exchange,提问作者Minh Ho
相关产品推荐
相关产品推荐

