You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对比RecyclerView选项与Firebase Realtime Database存储的正确答案

问答应用RecyclerView批量批改实现方案

你正在开发的问答应用数据库结构如下:
数据库结构示意图
现有单题批改逻辑运行正常,要实现所有题目批量批改,核心需要解决两个问题:

  1. 单题批改方法中使用全局的rgrex、resp1/resp2/resp3控件,只能对应单个题目,无法匹配RecyclerView每个独立条目里的控件
  2. 每次批改单题都单独请求Firebase,效率低,也不适合批量处理场景

实现步骤

步骤1:改造RecyclerView.Adapter,存储用户选择和题目数据

在Adapter里存储所有题目列表,以及每个题目的用户选择,避免RecyclerView复用时选择混乱,同时对外暴露数据获取接口:

public class PreguntaAdapter extends RecyclerView.Adapter<PreguntaAdapter.PreguntaHolder> {
    // 所有题目数据,初始化时一次性从Firebase拉取
    private List<PreguntaExamen> preguntaList;
    // 存储用户选择:key为条目position,value为选中的选项序号1/2/3,0代表未选择
    private SparseIntArray userSelections = new SparseIntArray();
    // 是否处于已批改状态,用来处理屏幕外条目UI更新
    private boolean isCorrected = false;

    public PreguntaAdapter(List<PreguntaExamen> list) {
        this.preguntaList = list;
    }

    public SparseIntArray getUserSelections() {
        return userSelections;
    }

    public List<PreguntaExamen> getPreguntaList() {
        return preguntaList;
    }

    public void setCorrected(boolean corrected) {
        isCorrected = corrected;
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public PreguntaHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_pregunta, parent, false);
        return new PreguntaHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull PreguntaHolder holder, int position) {
        PreguntaExamen pregunta = preguntaList.get(position);
        holder.resp1.setText(pregunta.getOpcion1());
        holder.resp2.setText(pregunta.getOpcion2());
        holder.resp3.setText(pregunta.getOpcion3());

        // 重置监听器避免复用冲突
        holder.rgPregunta.setOnCheckedChangeListener(null);
        holder.rgPregunta.clearCheck();
        // 回显已选选项
        int select = userSelections.get(position, 0);
        if (select != 0) {
            switch (select) {
                case 1: holder.rb1.setChecked(true); break;
                case 2: holder.rb2.setChecked(true); break;
                case 3: holder.rb3.setChecked(true); break;
            }
        }

        // 已批改状态下更新UI、禁用选择
        if (isCorrected) {
            int correct = Integer.parseInt(pregunta.getCorrecta());
            holder.resp1.setTextColor(Color.RED);
            holder.resp2.setTextColor(Color.RED);
            holder.resp3.setTextColor(Color.RED);
            switch (correct) {
                case 1: holder.resp1.setTextColor(Color.GREEN); break;
                case 2: holder.resp2.setTextColor(Color.GREEN); break;
                case 3: holder.resp3.setTextColor(Color.GREEN); break;
            }
            holder.rgPregunta.setEnabled(false);
            for (int i = 0; i < holder.rgPregunta.getChildCount(); i++) {
                holder.rgPregunta.getChildAt(i).setEnabled(false);
            }
            return;
        }

        // 监听用户选择
        holder.rgPregunta.setEnabled(true);
        holder.rgPregunta.setOnCheckedChangeListener((group, checkedId) -> {
            int s = 0;
            if (checkedId == R.id.rb1) s = 1;
            else if (checkedId == R.id.rb2) s = 2;
            else if (checkedId == R.id.rb3) s = 3;
            userSelections.put(position, s);
        });
    }

    @Override
    public int getItemCount() {
        return preguntaList.size();
    }

    public static class PreguntaHolder extends RecyclerView.ViewHolder {
        RadioGroup rgPregunta;
        RadioButton rb1, rb2, rb3;
        TextView resp1, resp2, resp3;
        public PreguntaHolder(@NonNull View itemView) {
            super(itemView);
            rgPregunta = itemView.findViewById(R.id.rg_pregunta);
            rb1 = itemView.findViewById(R.id.rb1);
            rb2 = itemView.findViewById(R.id.rb2);
            rb3 = itemView.findViewById(R.id.rb3);
            resp1 = itemView.findViewById(R.id.tv_resp1);
            resp2 = itemView.findViewById(R.id.tv_resp2);
            resp3 = itemView.findViewById(R.id.tv_resp3);
        }
    }
}

步骤2:页面初始化时一次性拉取所有题目数据

不需要每次批改再单独请求Firebase,初始化列表时就把所有题目(包含正确答案)拉取到本地:

// 页面onCreate方法中添加
database.child("Enfermeria").addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        List<PreguntaExamen> preguntaList = new ArrayList<>();
        for (DataSnapshot ds : snapshot.getChildren()) {
            PreguntaExamen p = ds.getValue(PreguntaExamen.class);
            if (p != null) {
                preguntaList.add(p);
            }
        }
        myAdapter = new PreguntaAdapter(preguntaList);
        recyclerView.setAdapter(myAdapter);
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {}
});

步骤3:修改批改按钮点击逻辑,批量处理所有题目

直接遍历本地存储的题目和用户选择,一次性完成所有题目的批改:

btnacab.setOnClickListener(v -> {
    pauseTimer();
    if (!corregido) {
        int totalScore = 0;
        SparseIntArray selections = myAdapter.getUserSelections();
        List<PreguntaExamen> preguntaList = myAdapter.getPreguntaList();
        
        // 遍历所有题目计算得分
        for (int i = 0; i < preguntaList.size(); i++) {
            PreguntaExamen p = preguntaList.get(i);
            int correct = Integer.parseInt(p.getCorrecta());
            int userSelect = selections.get(i, 0);
            if (userSelect == correct) {
                totalScore++;
            }
        }
        
        // 更新得分
        tvpuntu.setText("Puntuación: " + totalScore + "/" + preguntaList.size());
        // 标记为已批改,刷新RecyclerView更新所有条目UI
        myAdapter.setCorrected(true);
        corregido = true;
        btnacab.setText("SALIR");
    } else {
        Intent i = new Intent(ModeloExamen3.this, GeneralTest.class);
        startActivity(i);
    }
});

注意事项

  • 该方案一次性拉取所有题目到本地,减少了Firebase请求次数,响应速度更快
  • 批改状态放在Adapter中处理,即便是超出屏幕的条目,滚动时也会自动更新选项颜色,不会出现UI遗漏的问题
  • 所有用户选择都存储在Adapter中,避免了RecyclerView条目复用导致的选择错乱问题

内容的提问来源于stack exchange,提问作者Adrian S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 23:27:07