DiffUtils更新条目时areContentsTheSame恒返回true,Adapter不更新问题
RecyclerView Adapter 提交更新后未刷新条目问题解决
问题场景
UI层执行以下代码尝试更新列表条目:
val toMutableList = mAdapter.currentList.toMutableList() // 更新第5个位置的数据 val deviceItem = toMutableList[5] deviceItem.deviceEntity.onLineRefresh = false mAdapter.submitList(toMutableList)
对应的DiffUtil.ItemCallback实现如下:
override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean { TLog.d("DeviceListAdapter", "areItemsTheSame: ") return oldItem.deviceId == newItem.deviceId } override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean { return oldItem == newItem }
执行后发现Adapter并未更新目标条目,且areContentsTheSame方法始终返回true。
问题原因
currentList.toMutableList()只是做了浅拷贝——新列表里的DataItem对象和原列表的对象引用完全一致。修改deviceItem.deviceEntity.onLineRefresh时,原列表中的对应对象也被同步修改了。当submitList触发DiffUtil对比时,新旧条目本质是同一个对象,oldItem == newItem自然返回true,DiffUtil判定内容无变化,因此不会触发条目刷新。
解决方案
必须对列表中的每个DataItem进行深拷贝,让新列表里的对象都是全新实例,修改新对象的属性不会影响原列表的对象。
示例实现(需根据你的DataItem结构调整深拷贝逻辑):
// 给DataItem添加深拷贝方法(如果是data class,可借助copy方法实现) data class DataItem( val deviceId: String, val deviceEntity: DeviceEntity ) { fun deepCopy(): DataItem { // 若DeviceEntity还有嵌套对象,需递归拷贝所有属性 return copy( deviceEntity = deviceEntity.copy(onLineRefresh = deviceEntity.onLineRefresh) ) } } // UI层更新代码修改为: val newList = mAdapter.currentList.map { it.deepCopy() }.toMutableList() val deviceItem = newList[5] deviceItem.deviceEntity.onLineRefresh = false mAdapter.submitList(newList)
处理后,新列表的DataItem都是独立实例,DiffUtil对比时会检测到属性变化,areContentsTheSame返回false,进而触发目标条目刷新。
内容的提问来源于stack exchange,提问作者zeng li
相关产品推荐
相关产品推荐

