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

如何在RecyclerView中实现单选AlertDialog并正确展示选择结果

问题描述

我是AlertDialog开发新手,想实现一个单选AlertDialog,把选择结果和递增计数器一起显示在RecyclerView的TextView里。查了很多文档,都是把单选结果显示在Toast或单个TextView的方案。现在我的代码有问题,尝试多次后这是最接近预期的版本:能设置最新选择项,但点击按钮后其他选择项会变成类似内存分配的内容。其中dialogAlert()里的tv_choice.setText(multiItems[i])是问题所在,需要帮忙解决。

(截图说明:RecyclerView条目里的选择项显示为类似android.app.AlertDialog@xxxxxx的内存地址字符串)


原代码

MainActivity

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding
private val itemsList = generateItemsList()
private val adapter = MyAdapter(itemsList)
var count = 0

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    recyclerView.adapter = adapter
    recyclerView.layoutManager = LinearLayoutManager(this)
    recyclerView.setHasFixedSize(false)
    binding.button.setOnClickListener {
        addItemsToRecyclerView()
    }
}

private fun generateItemsList(): ArrayList<Items> {
    return ArrayList()
}
fun addItemsToRecyclerView() {
    val addItems = Items(getCount(), "Your Choice Is:", dialogAlert())
    itemsList.add(addItems)
    adapter.notifyItemInserted(itemsList.size - 1)
}
private fun getCount(): String {
    count += 1
    return count.toString()
}
fun dialogAlert(): String {
    val multiItems = arrayOf("Item 1", "Item 2", "Item 3")
    val singleChoice = AlertDialog.Builder(this)
        .setTitle("Choose one:")
        .setSingleChoiceItems(multiItems, 1) { dialogInterface, i ->
            tv_choice.setText(multiItems[i])

        }
        .setPositiveButton("ok") { _, _ ->
        }
        .create()
    singleChoice.show()
    val singleChoiceString = singleChoice.toString()
    return singleChoiceString
}
}

Adapter

class MyAdapter(private val rvDisplay: MutableList<Items>) : RecyclerView.Adapter<MyAdapter.AdapterViewHolder>(){

class AdapterViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
    val textView1: TextView = itemView.findViewById(R.id.tv_count)
    val textView2: TextView = itemView.findViewById(R.id.tv_choice_string)
    val textView3: TextView = itemView.findViewById(R.id.tv_choice)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AdapterViewHolder {
    val myItemView = LayoutInflater.from(parent.context).inflate(
        R.layout.rv_items,
        parent, false
    )
    return AdapterViewHolder(myItemView)
}

override fun onBindViewHolder(holder: MyAdapter.AdapterViewHolder, position: Int) {
    val currentDisplay = rvDisplay[position]
    holder.itemView.apply {
        holder.textView1.text = currentDisplay.count
        holder.textView2.text = currentDisplay.choiceString
        holder.textView3.text = currentDisplay.choice
    }
}

override fun getItemCount() = rvDisplay.size
}

问题分析
  1. 异步逻辑错误:AlertDialog是弹窗,用户选择是异步操作,但原代码里dialogAlert()会立即返回,此时用户还没选择内容,返回的singleChoice.toString()是AlertDialog对象的内存地址,这就是条目显示奇怪内容的原因。
  2. 直接操作RecyclerView条目:原代码直接修改tv_choice,但RecyclerView条目是复用的,会导致其他条目显示混乱,违反了RecyclerView通过数据驱动UI的设计规范。

修复方案

核心调整

等待用户完成选择并点击确定后,再创建数据条目添加到RecyclerView,通过数据类传递选择内容,让Adapter负责UI绑定。

修复后的MainActivity

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private val itemsList = generateItemsList()
    private val adapter = MyAdapter(itemsList)
    var count = 0
    // 保存用户当前选择的条目,默认对应弹窗初始选中项
    private var selectedItem = "Item 2"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.recyclerView.adapter = adapter
        binding.recyclerView.layoutManager = LinearLayoutManager(this)
        binding.recyclerView.setHasFixedSize(false)
        
        binding.button.setOnClickListener {
            showSingleChoiceDialog()
        }
    }

    private fun generateItemsList(): ArrayList<Items> {
        return ArrayList()
    }

    // 显示单选弹窗,用户确认后再添加条目
    private fun showSingleChoiceDialog() {
        val multiItems = arrayOf("Item 1", "Item 2", "Item 3")
        AlertDialog.Builder(this)
            .setTitle("Choose one:")
            .setSingleChoiceItems(multiItems, 1) { _, i ->
                // 实时保存用户选择的内容
                selectedItem = multiItems[i]
            }
            .setPositiveButton("ok") { _, _ ->
                // 用户点击确定后,添加条目到RecyclerView
                addItemsToRecyclerView()
            }
            .create()
            .show()
    }

    private fun addItemsToRecyclerView() {
        val addItems = Items(getCount(), "Your Choice Is:", selectedItem)
        itemsList.add(addItems)
        adapter.notifyItemInserted(itemsList.size - 1)
    }

    private fun getCount(): String {
        count += 1
        return count.toString()
    }
}

补充Items数据类(原代码缺失)

data class Items(
    val count: String,
    val choiceString: String,
    val choice: String
)

修复后的Adapter(仅补充完整语法)

class MyAdapter(private val rvDisplay: MutableList<Items>) : RecyclerView.Adapter<MyAdapter.AdapterViewHolder>() {

    class AdapterViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        val textView1: TextView = itemView.findViewById(R.id.tv_count)
        val textView2: TextView = itemView.findViewById(R.id.tv_choice_string)
        val textView3: TextView = itemView.findViewById(R.id.tv_choice)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AdapterViewHolder {
        val myItemView = LayoutInflater.from(parent.context).inflate(
            R.layout.rv_items,
            parent, false
        )
        return AdapterViewHolder(myItemView)
    }

    override fun onBindViewHolder(holder: MyAdapter.AdapterViewHolder, position: Int) {
        val currentDisplay = rvDisplay[position]
        holder.textView1.text = currentDisplay.count
        holder.textView2.text = currentDisplay.choiceString
        holder.textView3.text = currentDisplay.choice
    }

    override fun getItemCount() = rvDisplay.size
}

修复说明
  1. 移除了错误的dialogAlert()方法,改用showSingleChoiceDialog(),在单选回调中保存用户选择,点击确定后再触发添加条目逻辑,确保拿到正确的选择内容。
  2. 不再直接操作RecyclerView的条目TextView,而是通过Items数据类传递内容,让Adapter负责UI绑定,符合RecyclerView的设计规范。
  3. 补充了缺失的Items数据类,保证数据传递的完整性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 07:48:42