【问题标题】:Android RecyclerView Paging issueAndroid RecyclerView 分页问题
【发布时间】:2020-06-22 15:12:37
【问题描述】:

我正在关注this example 实现分页库,使用TMDB Api。

当我向下滚动列表到达边界条件时,它总是会向上滚动到第 1 页。

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

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

我想问题是当我向下滚动列表时调用了“LoadType = PREPEND”。适配器首先 APPEND 下一页,然后在 下一页 顶部检测到边界条件并决定执行 PREPEND,这会导致问题吗?我不知道如何解决这个问题。我已经尝试更改寻呼机的配置,但它不起作用。

You may find my code here.

提前致谢!

【问题讨论】:

    标签: android android-recyclerview android-paging


    【解决方案1】:

    我遇到了同样的问题,但对我来说,解决方案是从 SearchRepositoriesActivity 中删除以下行:

    private fun initSearch(query: String) {
    
        /* Some code here */
    
        // Remove these lines
        /*
        lifecycleScope.launch {   
            @OptIn(ExperimentalPagingApi::class)
            adapter.dataRefreshFlow.collect {
                binding.list.scrollToPosition(0)
            }
        }
        */
    }
    

    您可以在存储库上看到它here。这是在代码实验室中引入的,因此一旦请求(用于新的存储库搜索)完成,RecyclerView 就会滚动回顶部,这正是我发生的事情:RecyclerView 仅在 OkHttp 记录后才上升它收到了请求的结果。

    我无法完全理解为什么这仅适用于网络实现,而不适用于网络 + 数据库。如果我正确理解代码,则应该只在发生LoadState.REFRESH 事件时通知此流。我相信有一个隐藏的LoadState.REFRESH 正在发送,但在RemoteMediator 上没有收到。一旦我删除了上面的代码,屏幕仍然会闪烁,因为它很快就会进入Loading 状态。您可以通过将日志添加到addLoadStateListener(可用here)来查看它,如下所示:

    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 */
    }
    

    显示以下日志:

    如您所见,Room 在追加发生后会更改刷新状态。

    【讨论】:

    • 您好 Eduardo,您的提示在一年后仍然有用!但是您是否设法修复屏幕闪烁/冻结?看起来列表是分几个步骤更新的,而不仅仅是一个。我不明白为什么原来的android-paging 样本没有这个问题。
    • 我不记得了,已经有一段时间了。但我看到他们在一个单独的分支中对 codelab 存储库进行了一些更改。你可以试试this implementation 看看它是否有效。请注意,他们使用loadState.mediator 而不是loadState.source 来检查加载状态。
    • 感谢您的回答!看起来我有另一个问题,需要一个单独的问题。由于某种原因,分页库不使用 loadState=APPEND 调用 load 函数
    【解决方案2】:

    我遇到了同样的问题,但我找到了解决方案。 这应该是因为数据库索引。检查你的实体类的主键,一般是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
    

    【讨论】:

    • 感谢您的回答,我已经重新定义了自动生成的主键,但仍然遇到同样的问题。
    猜你喜欢
    • 2020-06-12
    • 1970-01-01
    • 2018-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多