请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

老师,当RecyclerView使用Diff去更新数据遇到一个问题

  1. 数据模型
//实现了老师的DiffUiDataCallback.UiDataDiffer
data class Main(val id: Int, val name: String) : DiffUiDataCallback.UiDataDiffer<Main> {
        override fun isSame(old: Main): Boolean {
            return this === old
        }

        override fun isUiContentSame(old: Main): Boolean {
            return this == old
        }
    }
  1. 一个简单的Adapter
class Adapter(val dataList: MutableList<Main>) : RecyclerView.Adapter<Adapter.ViewHolder>() {
        class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            val text = itemView.findViewById<TextView>(R.id.name)
        }

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

        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            Log.d("打印这个ViewHolder"," $holder")
            holder.text.text = dataList[position].name
        }

        override fun getItemCount(): Int {
            return dataList.size
        }
    }
  1. 当新数据到来时更新
val oldList = adapter.dataList
val newList = 刷新得到的新数据
// 进行数据对比
val callback: DiffUtil.Callback = DiffUiDataCallback(oldList, newList)
val result = DiffUtil.calculateDiff(callback)

//增量更新
adapter.dataList.clear()
adapter.dataList.addAll(newList)
result.dispatchUpdatesTo(adapter)
  1. 问题
    方便测试就假设获取的数据始终只有一个,只是每次刷新来的数据name会变换,当我去刷新获取新数据并进行增量更新时,打印出会发现ViewHolder会有两个实例,使用diff进行增量刷新就有这个问题,正常的notifyDataSetChanged没有。 只大概知道RecyclerView获取缓存的问题
//看打印结果可以发现每刷新就会去从缓存中加载上一个ViewHolder,也就是在一个位置实际上创建了两个ViweHolder
打印这个ViewHolder  ViewHolder{a42e991 position=0 id=-1, oldPos=-1, pLpos:-1 no parent}
打印这个ViewHolder  ViewHolder{6c1c7c4 position=0 id=-1, oldPos=-1, pLpos:-1 no parent}
打印这个ViewHolder  ViewHolder{a42e991 position=0 id=-1, oldPos=-1, pLpos:-1 no parent}
打印这个ViewHolder  ViewHolder{6c1c7c4 position=0 id=-1, oldPos=-1, pLpos:-1 no parent}

正在回答 回答被采纳积分+3

2回答

提问者 慕用1394343 2022-03-17 21:29:30

老师,面试官让说说做的某个项目,这个应该怎么去说? 我找个实习的,写过较为简单的项目,每次让介绍下,我都不知道咋去介绍好,本来项目不难,都是些基础的,感觉没啥说的🤣

0 回复 有任何疑惑可以回复我~
  • Qiujuer #1
    如果项目的确很简单,拿你可以从项目建设的一些框架上去讲,尽可能的突出你的设计想法。可能整个app并不复杂,但是你可以说你的设计思路,如何实现扩展性强、鲁棒性强,的整个架构。
    回复 有任何疑惑可以回复我~ 2022-03-28 14:38:50
Qiujuer 2022-02-14 15:48:58

这里打印holder没有啥意义呀

你应该打印的是 是否有新创建holder,以及bind时候的数据信息,而不是holder的信息。holder是recycer管理的,存在复用也存在自主创建的情况,这个都是正常的。

0 回复 有任何疑惑可以回复我~
  • 提问者 慕用1394343 #1
    onCreateViewHolder除了第一次加载时会执行一次外,第一次刷新也会执行,也就是创建了两个viewholder,后面在刷新就是两个viewholder轮流使用,复用机制会给每一个位置多创建viewholder吗? 但我不用diff就不会多创建
    回复 有任何疑惑可以回复我~ 2022-02-14 15:57:25
  • 提问者 慕用1394343 #2
    主要是他一个位置两个holder交换起来用就有问题了,比如holder中的view是有左右两页,第一次加载一个holder,我翻到右页,然后第一次刷新,它会创建第二个holder并bind,页面在左,  这时候我再刷新,它就使用第一个holder,看起来页面就在右边了,一直刷新就一直左右交换, 不知我的表述老师能不能明白。
    回复 有任何疑惑可以回复我~ 2022-02-14 16:07:36
  • Qiujuer 回复 提问者 慕用1394343 #3
    明白你的意思了,这个其实是不受控制的,本身属于recyclerview内部的缓存池的逻辑;一般我们的做法是在数据中存储view的关键信息,bind时根据这些值固定的设置view的状态;保证view与数据的一致性。
    回复 有任何疑惑可以回复我~ 2022-02-22 10:01:55
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信