我正在从网络加载帖子,为此我正在使用Paging 3,但现在的问题是我的列表项包含 Like/Dislike 按钮,假设单击Like,那么如何在不重新加载整个数据集的情况下更新该项目的数据?
我已阅读此android-pagedlist-updates,但似乎这适用于较旧的 Paging 2 或 1,那么在Paging 3中实现这一目标的完美方法是什么
我正在从网络加载帖子,为此我正在使用Paging 3,但现在的问题是我的列表项包含 Like/Dislike 按钮,假设单击Like,那么如何在不重新加载整个数据集的情况下更新该项目的数据?
我已阅读此android-pagedlist-updates,但似乎这适用于较旧的 Paging 2 或 1,那么在Paging 3中实现这一目标的完美方法是什么
我通过以下机制克服了这一挑战。维护内部 Hashmap 以保存键和对象,将此内部 hashmap 保存在您的 pagedlist 适配器中。随着列表的滚动,您将通过使用它的某个唯一键将远程喜欢/不喜欢作为初始状态添加到内部哈希映射中,因为该键是唯一的,您将不会复制,然后您将这个内部哈希映射用于您的更新 UI。
喜欢和不喜欢的 onClick 侦听器将更新此内部哈希图。再次内部哈希图是 UI 更新的参考。
解决方案很简单 - 在另一个内部 hashmap 上收集有用的数据以供以后操作。
我找到了一种解决方法,您可以使用它来实现这一目标,并提供了我正在使用的代码库的一些背景:
存储库代码:
override fun getPetsList(): Flow<PagingData<Pets>> {
return Pager(
config = PagingConfig(
pageSize = 15,
enablePlaceholders = false,
prefetchDistance = 4
),
pagingSourceFactory = {
PetDataSource(petService = petService)
}
).flow
}
视图模型代码:
// create a hashmap that stores the (key, value) pair for the object that have changed like (id:3, pet: fav=true .... )
viewModelScope.launch {
petRepository.getPetsList()
.cachedIn(viewModelScope)
.collect {
_petItems.value = it
}
}
现在是映射和所有魔法发生的片段代码
viewModel.petItems.observe(viewLifecycleOwner) { pagingData ->
val updatedItemsHashMap = viewModel.updatedPetsMap
val updatedPagingData = pagingData.map { pet ->
if (updatedItemsHashMap.containsKey(pet.id))
updatedItemsHashMap.getValue(pet.id)
else
pet
}
viewLifecycleOwner.lifecycleScope.launch {
petAdapter.submitData(updatedPagingData)
}
}
这就是实现这一点的方法,关键是对从存储库发出的 pagingData 进行映射。
不起作用的事情:
_petItems.value = PagingData.from(yourList)
这不起作用,因为根据文档,这用于静态列表,并且您会失去分页 3.0 附带的分页功能。所以映射 pagingData 似乎是唯一的方法。
在 Paging3 中,您仍然需要依赖PagingSource.invalidate
来提交更新,这与其说是不变性,不如说是关于拥有单一的事实来源。
通常,执行此操作的正确方法是更新支持数据集并调用invalidate
,这将触发不应导致任何 UI 更改的 REFRESH + DiffUtil,但保证如果该页面被删除并重新获取,加载的页面仍将保持最新。最简单的方法是使用已经内置自失效的 PagingSource 实现,例如 Room 提供的实现,只需更新喜欢/不喜欢按钮的相应行 onClick 即可。
有一个开放的错误跟踪工作以支持使用 Flow<> 对列表进行高度频繁、精细的更新,如果这是您的用例,您可以在此处关注:https ://issuetracker.google.com/160232968