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

Android中如何获取RecyclerView的所有ViewHolder?

解决RecyclerView无法获取所有题目答案的问题

首先得明确:RecyclerView的核心设计就是复用ViewHolder,所以试图获取所有ViewHolder(包括已回收的)本身就是违背它的设计理念的,这也是你遇到问题的根本原因。你的测验应用里,正确的思路应该是把「用户答案」和「UI载体(ViewHolder)」彻底分离,用数据模型来存储所有答案,而不是依赖ViewHolder。

具体解决方案步骤:

  • 第一步:定义数据模型类
    专门创建一个Question类来存储题目的所有信息,包括用户的选择答案。这样不管ViewHolder是否被回收,数据都安全存在模型里:

    data class Question(
        val questionId: Int,
        val questionText: String,
        val options: List<Option>,
        var selectedOptionId: Int? = null // 用来存储用户选中的选项ID
    )
    
    data class Option(
        val optionId: Int,
        val optionText: String
    )
    
  • 第二步:在选项RecyclerView中更新数据模型
    每个题目的选项列表是子RecyclerView,在它的Adapter里,用户点击选项时直接更新对应Question对象的selectedOptionId,而不是在ViewHolder里存状态:

    class OptionsAdapter(
        private val options: List<Option>,
        private val currentSelectedId: Int?,
        private val onOptionClick: (Int) -> Unit
    ) : RecyclerView.Adapter<OptionsAdapter.OptionViewHolder>() {
    
        inner class OptionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            val optionText: TextView = itemView.findViewById(R.id.tv_option)
            val optionRadio: RadioButton = itemView.findViewById(R.id.rb_option)
        }
    
        override fun onBindViewHolder(holder: OptionViewHolder, position: Int) {
            val option = options[position]
            holder.optionText.text = option.optionText
            // 恢复之前的选中状态
            holder.optionRadio.isChecked = option.optionId == currentSelectedId
    
            holder.itemView.setOnClickListener {
                // 点击时通知外部更新Question的选中答案
                onOptionClick(option.optionId)
            }
        }
    
        // ... 省略其他必要方法
    }
    
  • 第三步:在题目RecyclerView中绑定数据与回调
    在题目Adapter的onBindViewHolder里,给子RecyclerView的Adapter传入当前题目的选中状态,以及更新答案的回调:

    class QuestionsAdapter(
        private val questions: MutableList<Question>
    ) : RecyclerView.Adapter<QuestionsAdapter.QuestionViewHolder>() {
    
        inner class QuestionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            val questionText: TextView = itemView.findViewById(R.id.tv_question)
            val optionsRv: RecyclerView = itemView.findViewById(R.id.rv_options)
        }
    
        override fun onBindViewHolder(holder: QuestionViewHolder, position: Int) {
            val currentQuestion = questions[position]
            holder.questionText.text = currentQuestion.questionText
    
            // 初始化选项Adapter,传入当前选中ID和回调
            val optionsAdapter = OptionsAdapter(
                currentQuestion.options,
                currentQuestion.selectedOptionId
            ) { selectedId ->
                // 更新当前Question的选中答案
                currentQuestion.selectedOptionId = selectedId
            }
            holder.optionsRv.adapter = optionsAdapter
            // 别忘了设置LayoutManager
            holder.optionsRv.layoutManager = LinearLayoutManager(holder.itemView.context)
        }
    
        // ... 省略其他必要方法
    }
    
  • 第四步:获取所有题目的答案
    测验结束时,你根本不需要管RecyclerView的ViewHolder,直接遍历你维护的questions列表就行:

    // 遍历所有题目,收集答案
    val allAnswers = questions.map { question ->
        question.questionId to question.selectedOptionId
    }.toMap()
    // allAnswers就是所有题目的答案映射,不管题目是否在屏幕上可见
    

关于RecyclerView是否合适的疑问:

你之前觉得用RecyclerView不合适,其实是因为错误地把数据存在了ViewHolder里。只要做好数据与UI的分离,RecyclerView的复用机制在题目数量较多时反而能帮你节省大量内存,避免因为创建过多View导致的性能问题。如果题目数量很少,用LinearLayout也可以,但RecyclerView依然是更规范的选择。

内容的提问来源于stack exchange,提问作者Seles Calin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:12:38