分页3-数据库多次更新后列表滚动到开头

Nat*_*hac 5 android kotlin android-paging android-paging-library android-paging-3

我将 Paging 3 与 RemoteMediator 和 Room 结合使用,通过 PagingDataAdapter 在 RecyclerView 中显示项目列表。我们遇到一个问题,当数据库中保存的基础数据多次更新时(在某些情况下),会导致列表跳转到开头。我已经成功创建了一个可重现的场景:

  • 我向下滚动到第二页
  • 我通过应用程序检查执行 SQL 更新语句,更改所显示项目之一的属性。这会触发 PagingSource 失效。项目 UI 已正确更新。滚动位置不会改变。已加载的页面(第一页和页面 > 2)似乎已从基于打印日志适配器的回收器视图中删除。仅当前可见页面保持加载状态。

然后我执行以下操作之一:

  • 我立即执行另一个 SQL 更新语句,更改任何显示项目的属性。我期望与第一次更新时的行为相同。然而,这次列表跳回第一页。
  • 或者,我们滚动回到列表顶部。分页库从数据库加载第一页。然后我们向下滚动回到第二页。我们执行相同的更新语句。这次滚动位置没有改变

看来潜在的问题是,在数据已经失效一次并且除当前页面之外的所有页面都已从回收器视图中删除后,分页库无法正确处理额外的数据库失效。

我的问题是:

  • 第二次更新后不保留滚动位置是否是预期行为?这是我这边的实现问题还是分页库中的错误?
  • 即使只有一项实际更改,除当前页面之外的所有页面都会从 RecyclerView 中删除,这是预期的行为吗?这可能是“DiffUtil.ItemCallback”问题吗?
  • 实施占位符可以解决问题吗?

存储库中的相关代码:

  @MainThread
  fun fetchNewData(...): LiveData<PagingData<DisplayCard>> {
    val pagingSourceFactory = ... // Get appropriate PagingSource based on some conditions

    @OptIn(ExperimentalPagingApi::class)
    return Pager(
      config = PagingConfig(
        pageSize = DiscussionUseCase.PAGE_SIZE, // PAGE_SIZE = 20
        prefetchDistance = 2,
        enablePlaceholders = false,
        initialLoadSize = DiscussionUseCase.PAGE_SIZE // PAGE_SIZE = 20
      ),
      remoteMediator = ItemRemoteMediator(...),
      pagingSourceFactory = pagingSourceFactory
    ).liveData
  }
Run Code Online (Sandbox Code Playgroud)

房间查询之一 - 其他查询非常相似:

@Query("SELECT d.* FROM discussions AS d WHERE ... ORDER BY datetime(d.lastPostDate) DESC")
fun getCardList(query: String?): PagingSource<Int, DisplayCard>
Run Code Online (Sandbox Code Playgroud)

ViewModel的相关代码:

  /**
   * MediatorLiveData that is triggered every time one of the filters is changed and we have to fetch fresh data
   */
  val listChanges = MediatorLiveData<ListChangesAction>()

  val repoResult = listChanges.switchMap {
    updateUI()
    fetchNewData().cachedIn(viewModelScope)
  }
Run Code Online (Sandbox Code Playgroud)

Activity 的相关代码:

viewModel.repoResult.observe(this) { pagingData ->
  adapter.submitData(lifecycle, pagingData)
}
Run Code Online (Sandbox Code Playgroud)

Ser*_*hat 2

我遇到了同样的问题。您可以在 PagingConfig 中尝试enablePlaceHolders = true。