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
.
传回分页之前偏移密钥
我在刷新分页数据时遇到问题,我不确定需要如何设置刷新键才能正常工作。文档根本不清楚。 我有这个基数 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
.