如何在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 }
问题分析
- 异步逻辑错误:AlertDialog是弹窗,用户选择是异步操作,但原代码里
dialogAlert()会立即返回,此时用户还没选择内容,返回的singleChoice.toString()是AlertDialog对象的内存地址,这就是条目显示奇怪内容的原因。 - 直接操作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 }
修复说明
- 移除了错误的
dialogAlert()方法,改用showSingleChoiceDialog(),在单选回调中保存用户选择,点击确定后再触发添加条目逻辑,确保拿到正确的选择内容。 - 不再直接操作RecyclerView的条目TextView,而是通过
Items数据类传递内容,让Adapter负责UI绑定,符合RecyclerView的设计规范。 - 补充了缺失的
Items数据类,保证数据传递的完整性。
内容的提问来源于stack exchange,提问作者thatWaz96
相关产品推荐
相关产品推荐

