使用ListAdapter结合DiffUtil与LiveData时数据被覆盖而非追加的问题
解决ListAdapter提交新数据时覆盖原有数据而非追加的问题
嘿,我一眼就看出问题所在了——你现在的逻辑是每次请求新数据时直接替换掉旧列表,而不是把新数据追加进去!
问题根源分析
看你的ItemViewModel里的getItems方法:
fun getItems(start: Int = 1) { viewModelScope.launch { val items = repository.getItems(start) _items.value = items // 这里直接把新列表赋值,覆盖了旧数据! } }
每次调用这个方法,你都会把repository返回的新列表直接赋值给_items,这就相当于把之前的所有数据都丢掉了,换成了新的那一批。而ListAdapter.submitList()的作用是接收完整的新列表来更新UI,它不会自动帮你做数据追加的操作。
修复方案
你需要把新获取到的数据和现有的数据合并,然后再赋值给LiveData,具体修改如下:
1. 修改ItemViewModel的getItems方法
fun getItems(start: Int = 1) { viewModelScope.launch { val newItems = repository.getItems(start) // 获取当前已有的数据,如果还没有数据就用空列表兜底 val currentItems = _items.value ?: emptyList() // 合并新旧列表,注意要创建新的List实例(LiveData需要感知对象变化) _items.value = currentItems + newItems } }
这里的关键是currentItems + newItems——这个操作会生成一个全新的List对象,LiveData才能检测到数据变化,进而通知观察者去调用adapter.submitList()更新RecyclerView。
2. 确认FakeRepository的返回数据正确
要确保repository.getItems(start)返回的是从start开始的新条目,比如当你点击FAB传入start=9时,它应该返回id为9、10...的新Item,而不是重复或者覆盖之前的数据,这是追加功能生效的基础。
3. 你的DiffUtil实现没问题
顺便说一句,你的DiffUtilCallback和Item data class的写法都是正确的:
areItemsTheSame用id判断是否是同一个条目,符合DiffUtil的最佳实践areContentsTheSame用==比较(data class自动生成了equals方法),能正确判断内容是否变化
这样修改后,当你点击FAB时,新数据就会追加到原有列表的后面,而不是覆盖啦!
内容的提问来源于stack exchange,提问作者nurmat
相关产品推荐
相关产品推荐

