【问题标题】:How can we mutate items loaded using Paging 3 android?我们如何改变使用 Paging 3 android 加载的项目?
【发布时间】:2020-11-20 02:45:28
【问题描述】:

我正在从网络加载帖子,为此我使用Paging 3,但现在问题是我的列表项包含喜欢/不喜欢按钮,假设 喜欢被点击,那么如何在不重新加载整个数据集的情况下更新该项目的数据?

我已阅读此android-pagedlist-updates,但似乎这是针对较旧的 Paging 2 或 1,那么在 Paging 3

中实现这一目标的完美方法是什么

【问题讨论】:

  • 你能解决这个问题吗?

标签: android pagination android-architecture-components android-paging android-architecture-paging


【解决方案1】:

我通过以下机制克服了这一挑战。维护内部 Hashmap 以保存键和对象,将此内部 hashmap 保存在 pagedlist 适配器中。随着列表的滚动,您将通过使用它的某个唯一键将远程喜欢/不喜欢作为初始状态添加到内部哈希映射中,因为该键是唯一的,您将不会复制,然后您将这个内部哈希映射引用为您的更新 UI。

喜欢和不喜欢的 onClick 侦听器将更新此内部哈希图。再次内部 hashmap 是 UI 更新的参考。

解决方案很简单 - 在另一个内部哈希图上收集有用的数据以供以后操作。

【讨论】:

    【解决方案2】:

    我找到了一种解决方法,您可以使用它来实现这一目标,并提供了我正在使用的代码库的一些背景:

    • 我有一个 PagingDataAdapter(Pagination-3.0 适配器)作为回收器视图适配器。
    • 我有片段的视图模型
    • 我有一个返回 PaginationData 流的存储库
    • 并将此流作为 liveData 公开给片段

    存储库代码:

    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 似乎是唯一的方法。

    【讨论】:

      【解决方案3】:

      在 Paging3 中,您仍然需要依靠 PagingSource.invalidate 来提交更新,这与其说是不变性,不如说是关于拥有单一事实来源。

      通常,执行此操作的正确方法是更新支持数据集并调用invalidate,这将触发不应导致任何 UI 更改的 REFRESH + DiffUtil,但保证如果该页面被删除并重新获取,加载的页面仍然是最新的。最简单的方法是使用已经内置自失效的 PagingSource 实现,例如 Room 提供的实现,只需更新喜欢/不喜欢按钮的相应行 onClick。

      有一个开放的错误跟踪工作以支持使用 Flow 对列表进行高度频繁、精细的更新,如果这是您的用例,您可以在此处关注:https://issuetracker.google.com/160232968

      【讨论】:

      • 我正在考虑使用这里解释的 RemoteMediator developer.android.com/topic/libraries/architecture/paging/…,你是否也想使用类似的东西
      • 无论您是否使用 RemoteMediator,Pager 仍然需要一个 lambda,它在其构造函数中生成一个 PagingSource。所有加载和呈现的数据仍然基于 PagingSource 返回的内容。 RemoteMediator 仅允许您进行远程调用以在边界条件下获取附加数据(然后将其存储为 PagingSource),并传达该负载状态以在您的适配器上进行同步更新。
      猜你喜欢
      • 1970-01-01
      • 2022-12-04
      • 1970-01-01
      • 2021-06-09
      • 2020-11-17
      • 2021-12-13
      • 2022-09-27
      相关资源
      最近更新 更多