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

RecyclerView用ListAdapter定时更新后出现数据显示错误求助

问题分析与解决方案

疑问1:为何初始显示正确,后续更新出错?

因为RecyclerView的ViewHolder采用复用机制,你把codeView这类视图引用传给定时器后,定时器会一直持有这个引用。当原item滚出屏幕,对应的ViewHolder会被复用给新的可见item(比如你提到的第5位),但之前的定时器还在运行,当它完成倒计时时,会更新它持有的那个View——而此时这个View已经属于新的item了,所以就把旧item的数据错误地更新到了新item的视图上。首次显示时视图还没被复用,所以数据是对的,滚动后复用发生,问题就暴露了。

疑问2:正确的实现方式

核心原则是数据驱动UI,不让定时器持有视图引用,具体步骤如下:

1. 修复DiffCallback的内容判断逻辑

你当前的areContentsTheSame只判断了id,这会导致DiffUtil认为只要id相同,内容就没变化,不会触发UI更新。必须把需要更新的字段(比如你要刷新的code)加入判断:

private class TpaDiffCallBack : DiffUtil.ItemCallback<DataForWatch>() {
    override fun areItemsTheSame(oldItem: DataForWatch, newItem: DataForWatch): Boolean =
        oldItem.id == newItem.id

    override fun areContentsTheSame(oldItem: DataForWatch, newItem: DataForWatch): Boolean {
        // 对比所有可能变化的字段,这里加上code
        return oldItem.id == newItem.id && oldItem.code == newItem.code
    }
}

2. 用协程管理定时任务,只更新数据源

不要给每个视图绑定定时器,而是在ViewModel(或页面逻辑层)中为每个数据项启动协程定时任务,只更新数据源中的code字段,然后通知适配器更新单个item:

// 假设在ViewModel中
private val job = Job()
private val scope = CoroutineScope(Dispatchers.Main + job)

fun startTimers(dataList: MutableList<DataForWatch>, adapter: YourListAdapter) {
    dataList.forEachIndexed { index, data ->
        scope.launch {
            while (isActive) {
                delay(20000) // 20秒
                // 更新数据源中的code
                data.code = getCode(data) // 这里改成直接生成code赋值给数据项
                // 通知适配器更新单个item,避免全量刷新
                adapter.notifyItemChanged(index)
            }
        }
    }
}

// 页面销毁时取消所有协程,避免内存泄漏
override fun onCleared() {
    super.onCleared()
    job.cancel()
}

3. ViewHolder仅负责绑定数据

ViewHolder里只做数据绑定,不要处理任何定时器逻辑,确保每次复用ViewHolder时,都会绑定当前item的最新数据:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val data = getItem(position)
    holder.codeView.text = data.code
    // 其他视图绑定逻辑...
}

对已尝试方案的补充说明

  • 禁止视图复用:完全违背RecyclerView的设计初衷,必然导致性能急剧下降,绝对不可取。
  • 全量更新列表:会触发整个列表的重绘,即使只有一个item变化,DiffUtil的优化也无法完全抵消全量更新带来的开销,所以会出现闪烁和卡顿。而单个item更新只会刷新目标位置的视图,性能更优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 10:32:21