You need to enable JavaScript to run this app. Android RecyclerView滚动时动态添加的视图不受控重复错乱问题
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.02 07:09:04