Kotlin RecyclerView复用导致item颜色错乱、EditText数据异常问题求解
问题根因
你遇到的两个问题都是RecyclerView使用的常见错误,和position校验无关,根因分别如下:
任务列表颜色全部相同问题
- 核心错误1:
TextView.setTextColor()方法接收的是解析后的实际颜色值,你直接传入R.color.xxx格式的资源ID,系统会将资源ID误识别为颜色值,导致颜色显示异常。 - 次要错误:你将Adapter初始化和
setAdapter操作放在了遍历Firebase数据的for循环内部,每添加一条数据就重新设置一次Adapter,不仅严重影响性能,还可能出现数据加载过程中的展示异常。
带EditText的列表滚动时内容错乱问题
RecyclerView复用Holder时不会自动清空控件的旧状态,你缺少两个关键处理:
- 每次
onBindViewHolder时,没有给EditText设置当前position对应存储的输入内容 - 没有将EditText的输入内容实时同步到数据源,复用Holder时旧的输入监听会把内容写到错误的position对应的数据上
修复方案
任务列表修复
- 把Adapter初始化逻辑移出for循环,所有数据加载完成后只设置一次Adapter:
// 删除原循环内部的adapter初始化代码 for (document in result) { // 原有计算bgColor、添加数据到data列表的逻辑保留不变 } // 循环结束后再初始化Adapter,仅执行一次 val adapter = AllTasksAdapter(this, data) allTasksRecycler.adapter = adapter
- 修改Adapter中设置颜色的代码,将资源ID转成实际颜色:
// 把原来的holder.txtTaskName.setTextColor(t.bgColor!!)替换为下面的代码 holder.txtTaskName.setTextColor(ContextCompat.getColor(context, t.bgColor!!))
带EditText的列表修复
- 给你的字符实体类新增字段保存输入内容:
data class CharItem( val targetChar: Char, // 新增字段存储用户输入的内容 var userInput: String = "" )
- 在ViewHolder中存储TextWatcher避免重复绑定,每次绑定时先清理旧监听再设置新内容:
class CharViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val inputEt: EditText = itemView.findViewById(R.id.input_et) // 存储当前绑定的输入监听,复用时可以移除 var inputWatcher: TextWatcher? = null } override fun onBindViewHolder(holder: CharViewHolder, position: Int) { val item = mList[position] // 先移除旧监听,避免复用触发错误回调 holder.inputEt.removeTextChangedListener(holder.inputWatcher) // 设置当前position对应的存储的输入内容 holder.inputEt.setText(item.userInput) // 新建监听,输入内容实时同步到数据源 val watcher = object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit override fun afterTextChanged(s: Editable?) { item.userInput = s?.toString() ?: "" } } holder.inputWatcher = watcher holder.inputEt.addTextChangedListener(watcher) }
内容的提问来源于stack exchange,提问作者Tim Foster
相关产品推荐
相关产品推荐

