Android Kotlin中DiffUtil配合ListAdapter仅滚动时刷新视图怎么解决?
问题根因及修复方案
1. 修正外层适配器的DiffUtil逻辑
你当前FirstAdapter的areItemsTheSame错误使用了内容相等判断,该方法的作用是判断两个条目是否为同一个条目(仅判断唯一标识,不判断内容),正确实现如下:
private val comp = object : DiffUtil.ItemCallback<Group>() { override fun areItemsTheSame(oldItem: Group, newItem: Group): Boolean { // 用Group的唯一标识key判断是否为同一个条目 return oldItem.key == newItem.key } override fun areContentsTheSame(oldItem: Group, newItem: Group): Boolean { return oldItem.key == newItem.key && oldItem.value == newItem.value } }
2. 禁止直接修改原有列表实例,每次更新都生成新的列表副本
ListAdapter的DiffUtil依赖新旧两个不同的列表实例做差异对比,你直接修改原有oldlist实例后再postValue,DiffUtil会判定新旧列表为同一个对象,直接跳过差异计算,导致不会主动触发视图更新。修改addItemOnTop逻辑如下:
private fun addItemOnTop(text: String) { list.value?.let { oldlist -> // 生成新的外层列表副本 val newList = oldlist.toMutableList() if(top != null){ newList.add(0, item) }else{ // 生成新的Group副本+新的内层value列表副本 val oldFirstGroup = newList[0] val newValue = oldFirstGroup.value.toMutableList().apply { add(item) } val newFirstGroup = oldFirstGroup.copy(value = newValue) newList[0] = newFirstGroup } list.postValue(newList) } }
同时注意接口返回数据生成列表时,也每次都生成新的列表实例,不要复用旧实例。
3. 修正内层适配器的DiffUtil笔误
SecondAdapter的areContentsTheSame中存在笔误,oldItem.text == oldItem.text永远返回true,会导致text字段变化时检测不到更新,修正如下:
override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean { return oldItem.rr == newItem.rr && oldItem.text == newItem.text && oldItem.abc == newItem.abc }
4. 嵌套RecyclerView主动刷新内层列表
外层FirstAdapter的onBindViewHolder中,每次绑定条目时都要给内层SecondAdapter提交最新的value列表,不要只在ViewHolder初始化时提交一次:
override fun onBindViewHolder(holder: FirstViewHolder, position: Int) { val group = getItem(position) // 每次绑定都重新提交最新列表 holder.adapter.submitList(group.value.toList()) }
以上修复完成后,ListAdapter就能正常检测到列表差异,主动触发对应位置的视图更新,不需要手动调用notify方法或者滚动列表。
内容的提问来源于stack exchange,提问作者Compose Learner
相关产品推荐
相关产品推荐

