安卓RecyclerView分页问题

3

我正在按照这个例子来实现分页库,使用TMDB Api。

当我滚动列表到达边界条件时,它总是会滚回第一页。

我认为RemoteMediator类存在问题导致了这个问题,但我几乎是从Google的示例中复制的...

下面是我的日志。 我在这里向下滚动列表。Log

我想问题在于“LoadType = PREPEND”被调用时我向下滚动列表。适配器首先APPEND下一页,但然后检测到上一页的顶部边界条件,并决定进行PREPEND,导致出现问题吗? 我不确定如何解决这个问题。 我已经尝试更改pager的配置,但它不起作用。

您可以在此处找到我的代码。

谢谢!

2个回答

2

我曾经遇到过同样的问题,但是我的解决办法是从SearchRepositoriesActivity中删除以下行:

private fun initSearch(query: String) {

    /* Some code here */

    // Remove these lines
    /*
    lifecycleScope.launch {   
        @OptIn(ExperimentalPagingApi::class)
        adapter.dataRefreshFlow.collect {
            binding.list.scrollToPosition(0)
        }
    }
    */
}

你可以在代码库的这里查看它。在本实验中,这是为了使RecyclerView在请求(用于新存储库搜索的请求)完成后滚动回顶部,这正是我的情况:只有在OkHttp记录接收到请求结果后RecyclerView才回到顶部。

我无法完全理解为什么网络版本可以正常工作,但是网络+数据库就不行。如果我正确地理解了代码,那么当发生LoadState.REFRESH事件时,此流应该仅被通知一次。我认为存在一个隐藏的LoadState.REFRESH,但在RemoteMediator上没有接收到。一旦我删除了上面的代码,屏幕仍然会闪烁,因为它会迅速转移到Loading状态。您可以通过如下方式向addLoadStateListener添加日志(位于这里)来查看它:

adapter.addLoadStateListener {  loadState ->
        // Add this log
        Log.d("UI_PAGING", "source: ${loadState.source.refresh}, remote: ${loadState.refresh}")

        // Only show the list if refresh succeeds.
        binding.list.isVisible = loadState.source.refresh is LoadState.NotLoading
        // Show loading spinner during initial load or refresh
        binding.progressBar.isVisible = loadState.source.refresh is LoadState.Loading
        // Show the retry state if initial load or refresh fails.
        binding.retryButton.isVisible = loadState.source.refresh is LoadState.Error

        /* some other code here */
}

这里展示了以下日志:

Android Logs for Paging Library 3

从中可以看到,一旦发生追加操作,Room就会改变刷新状态。

你好Eduardo,你的提示在一年后仍然有用!但是你能解决屏幕闪烁/冻结的问题吗?看起来列表是分几步更新的,而不仅仅是一步。 我不明白为什么原始的“android-paging”示例没有这个问题。 - eraxillan
我不记得了,已经有一段时间了。但是我看到他们在一个单独的分支中对codelab存储库进行了一些更改。你可以尝试这个实现,看看它是否有效。请注意,他们使用loadState.mediator而不是loadState.source来检查加载状态。 - Eduardo macedo
谢谢回答!看起来我有另一个问题,需要提出单独的问题。由于某种原因,分页库不会使用loadState=APPEND调用“load”函数。 - eraxillan

0

我遇到了同样的问题,但是我找到了解决方案。 这可能是由于数据库索引引起的。检查您的实体类的主键,通常为id,但id的大小可能会混乱。当Room插入数据时,它将根据主键的大小进行插入,这会导致您的数据库和api响应数据的顺序错误。

解决方案是在您的实体类中重新定义另一个主键,并让它自动增长,例如databaseId,以便Room数据库的插入顺序正确。这可以解决列表滑动的问题。

@Entity(tableName = "articles")
data class Article(
    @PrimaryKey(autoGenerate = true)
    val databaseId: Int,
    @field:SerializedName("id")
    val id: Int,
    @field:SerializedName("title")
    val title: String,
    @field:SerializedName("apkLink")
    val apkLink: String,
    @field:SerializedName("audit")
    val audit: Int

1
谢谢您的回答,我已经重新定义了一个自动生成的主键,但仍然看到相同的问题。 - C.Chee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接