Paging 3 中间刷新

Paging 3 refresh in the middle

我在刷新分页数据时遇到问题,我不确定需要如何设置刷新键才能正常工作。文档根本不清楚。 我有这个基数 class 用于偏移分页,所以它变为 0-40、40-60、60-80 等等。这行得通,但是当我在收集中间并且我想使用 invalidate() 或 adapter.refresh() 刷新数据时,它会崩溃并显示以下消息:

java.lang.IllegalStateException: The same value, 40, was passed as the prevKey in two sequential Pages loaded from a PagingSource. Re-using load keys in PagingSource is often an error, and must be explicitly enabled by overriding PagingSource.keyReuseSupported.

启用后,它不会崩溃,但它的行为很奇怪,因为它从中间开始分页,我无法回到集合的开头,因为它不断地对相同的项目进行分页.

示例:

prevKey null, nextKey: 40 -> prevKey 40, nextKey: 60 -> prevKey 60, nextKey: 80

Invalidate()

prevKey 40, nextKey: 80 -> prevKey 40, nextKey: 60 // This is the case when it crashes without the keyReuseSupported flag.

我想回到开头,它卡在了 prevKey 40, nextKey: 60

abstract class OffsetPagingSource<Value : Any>(
    private val coroutineScope: CoroutineScope
) : PagingSource<Int, Value>() {

    abstract suspend fun queryFactory(
        size: Int,
        after: Int,
        itemCount: Boolean
    ): PagingResult<Value>?

    abstract suspend fun subscriptionFactory(): Flow<Any>?

    init {
        initSubscription()
    }

    private fun initSubscription() {
        coroutineScope.launch {
            try {
                subscriptionFactory()?.collect {
                    invalidate()
                }
            } catch (e: Throwable) {}
        }
    }

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Value> {
        val size = params.loadSize
        val after = params.key ?: 0

        return try {
            val result = queryFactory(size, after, true) ?: return LoadResult.Page(emptyList(), null, null)

            val totalCount = result.pageInfo.itemCount

            val nextCount = after + size

            val prevKey = if (after == 0) null else after
            val nextKey = if (nextCount < totalCount) nextCount else null

            LoadResult.Page(result.edges.mapNotNull { it.node }, prevKey = prevKey, nextKey)
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }

    override fun getRefreshKey(state: PagingState<Int, Value>): Int? {
        return state.anchorPosition?.let { anchorPosition ->
            val anchorPage = state.closestPageToPosition(anchorPosition)
            anchorPage?.prevKey
        }
    }
}

有谁知道如何解决这个问题?我不确定这是否是错误。分页 3 种强制分页工作的方式,而不是启用不同的方法。

抛出的异常警告您您正在使用相同的密钥加载不同的数据/页面。在您的示例中,无效后:

{ prevKey 40, nextKey: 80}, { prevKey 40, nextKey: 60 }

表示您希望对第一页之前的页面使用 params.key = 40 并重新加载第一页。即,您有:

page0: not loaded yet
page1: { prevKey 40, nextKey: 80 }
page2: { prevKey 40, nextKey: 60 }

表示您想使用 params.key 加载第 0 页和第 1 页。这可能是你想要的,但通常是一个错误,这是异常警告你的。

您可能一遍又一遍地重新加载同一页面的原因是,您使用从 key...key+pageSize 加载的相同逻辑来解释前置和附加,并且始终传递 prevKey = key.您可能需要检查 LoadParams is LoadParams.Prepend 并在 load 逻辑中偏移密钥,或者在将密钥作为 prevKey.

传回分页之前偏移密钥