android - 带有 RemoteMediator 的 Android Paging3:项目出现在列表的中间或可见的上方,看起来很乱
问题描述
我有一个来自 API 的项目列表。我正在使用带有 RemoteMedatior 的Paging3来使用 Room 在数据库中使用本地缓存来维护网络。我的问题是,当数据加载时,recyclerView看起来凌乱而有问题,项目出现在列表中间和可见项目之上,并且recyclerView不会滚动到列表顶部。看起来像这样。我已经尝试了 pageConfig 的pageSize、maxSize和prefetchDistance
的
各种值,但它没有帮助。
recylerview上的 setHasFixedSize 也不起作用。使用片段中的collectLatest收集流。我也尝试过正常收集并将流量更改为liveData。结果相同。知道如何纠正这个问题吗?
RemoteMediator 中的加载函数
@ExperimentalPagingApi
class RecipesMediator(
private val recipesApi: RecipesApi,
private val appDatabase: RecipesDatabase,
private val queries: HashMap<String, String>,
) : RemoteMediator<Int, Recipe>() {
override suspend fun load(loadType: LoadType, state: PagingState<Int, Recipe>): MediatorResult {
val queryId = queries[QUERY_DIET] + queries[QUERY_MEAL]
val page = when (loadType) {
LoadType.REFRESH -> 0
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
LoadType.APPEND -> appDatabase.remoteKeysDao().remoteKeysRecipeId(queryId).nextKey
}
queries[QUERY_OFFSET] = page.toString()
queries[QUERY_NUMBER] = "20"
try {
val response = recipesApi.getRecipes(queries)
appDatabase.withTransaction {
if (loadType == LoadType.REFRESH) {
appDatabase.remoteKeysDao().clearRemoteKeys()
appDatabase.recipesDao().clearRecipes()
}
val nextKey = page + 20
val keys = response.recipes.map {
RemoteKeys(query = queryId, nextKey = nextKey)
}
appDatabase.remoteKeysDao().insertAll(keys)
appDatabase.recipesDao().insertAllRecipes(response.recipes)
}
return MediatorResult.Success(endOfPaginationReached = response.recipes.isEmpty())
} catch (exception: IOException) {
return MediatorResult.Error(exception)
} catch (exception: HttpException) {
return MediatorResult.Error(exception)
}
}
我使用字符串作为远程密钥 ID,因为当我使用 API = LoadType.Append中的项目 ID 时,被多次调用并且只加载了第一页。它在这个问题中解释
nextPage是“page + 20”,因为这个 API(Spoonacular)不提供分页,虽然提供了参数 offset(要跳过的结果数)和 number(预期结果数),所以我将它们用于分页。
片段中的 UI 状态
recipesAdapter.addLoadStateListener { loadState ->
binding.apply {
recipesProgressBar.isVisible = loadState.mediator?.refresh is LoadState.Loading
recipesProgressBar.isVisible = loadState.source.refresh is LoadState.Loading
recipesRecyclerView.isVisible =loadState.mediator?.refresh is LoadState.NotLoading
recipesRecyclerView.isVisible =loadState.source.refresh is LoadState.NotLoading
buttonRecipesRetry.isVisible =loadState.mediator?.refresh is LoadState.Error
buttonRecipesRetry.isVisible =loadState.source.refresh is LoadState.Error
textViewRecipesError.isVisible =loadState.mediator?.refresh is LoadState.Error
textViewRecipesError.isVisible =loadState.source.refresh is LoadState.Error
if (loadState.source.refresh is LoadState.NotLoading &&
loadState.mediator?.refresh is LoadState.NotLoading &&
loadState.append.endOfPaginationReached &&
recipesAdapter.itemCount < 1
) {
recipesRecyclerView.isVisible = false
textViewEmpty.isVisible = true
} else {
textViewEmpty.isVisible = false
}
}
}
遥控钥匙
@Entity(tableName = "remoteKeys")
data class RemoteKeys
(@PrimaryKey val query: String, val nextKey: Int)
遥控钥匙道
@Dao
interface RemoteKeysDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(remoteKey: List<RemoteKeys>)
@Query("SELECT * FROM remoteKeys WHERE `query` = :query")
suspend fun remoteKeysId(query: String): RemoteKeys
@Query("DELETE FROM remoteKeys")
suspend fun clearRemoteKeys()
}
解决方案
推荐阅读
- php - 在 IIS 上运行的 PHP - 15 分钟后超时
- php - Chrome:当作为本地文件查看时,PHP 文件中的 HTML 内容不显示
- r - R:遍历数据框,提取多个变量的子集,然后存储在聚合数据集中
- android - 使用 RxJava、Kotlin 进行服务器轮询的单元测试
- python - 卡尔曼滤波器总是预测原点
- angular - npm start 上的 Angular v2 快速启动错误
- hibernate - org.hibernate.PropertyNotFoundException:在类 com.hibernate.demo.user 中找不到名字的 getter
- python - 两个不同的数据库连接同时 Python
- android - Fragment Android 中的 DatePicker 未显示
- jquery - 如何使用 jquery.ui.combify 设置选择对象的宽度