Android Paging 3 和 RemoteMediator 在用户未到达列表底部时请求列表
Android Paging 3 and RemoteMediator requests for list while user doesn't reached to bottom of the list
我正在使用 Android Paging 3,如您在 https://developer.android.com/topic/libraries/architecture/paging/v3-network-db 中所见。
当我 运行 应用程序 RemoteMediator 请求服务器获取列表,直到服务器上没有任何内容。
这里的重点是当用户到达列表底部时我们想要获取列表,但是 RemoteMediator 一直在请求直到获取服务器上的所有列表!
RemoteMediator.kt
@OptIn(ExperimentalPagingApi::class)
class ExampleRemoteMediator(
private val query: String,
private val database: RoomDb,
private val networkService: ExampleBackendService
) : RemoteMediator<Int, User>() {
val userDao = database.userDao()
val remoteKeyDao = database.remoteKeyDao()
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, User>
): MediatorResult {
return try {
// The network load method takes an optional String
// parameter. For every page after the first, pass the String
// token returned from the previous page to let it continue
// from where it left off. For REFRESH, pass null to load the
// first page.
val loadKey = when (loadType) {
LoadType.REFRESH -> null
// In this example, you never need to prepend, since REFRESH
// will always load the first page in the list. Immediately
// return, reporting end of pagination.
LoadType.PREPEND -> return MediatorResult.Success(
endOfPaginationReached = true
)
// Query remoteKeyDao for the next RemoteKey.
LoadType.APPEND -> {
val remoteKey = database.withTransaction {
remoteKeyDao.remoteKeyByQuery(query)
}
// You must explicitly check if the page key is null when
// appending, since null is only valid for initial load.
// If you receive null for APPEND, that means you have
// reached the end of pagination and there are no more
// items to load.
if (remoteKey.nextKey == null) {
return MediatorResult.Success(
endOfPaginationReached = true
)
}
remoteKey.nextKey
}
}
// Suspending network load via Retrofit. This doesn't need to
// be wrapped in a withContext(Dispatcher.IO) { ... } block
// since Retrofit's Coroutine CallAdapter dispatches on a
// worker thread.
val response = networkService.searchUsers(query, loadKey)
// Store loaded data, and next key in transaction, so that
// they're always consistent.
database.withTransaction {
if (loadType == LoadType.REFRESH) {
remoteKeyDao.deleteByQuery(query)
userDao.deleteByQuery(query)
}
// Update RemoteKey for this query.
remoteKeyDao.insertOrReplace(
RemoteKey(query, response.nextKey)
)
// Insert new users into database, which invalidates the
// current PagingData, allowing Paging to present the updates
// in the DB.
userDao.insertAll(response.users)
}
MediatorResult.Success(
endOfPaginationReached = response.nextKey == null
)
} catch (e: IOException) {
MediatorResult.Error(e)
} catch (e: HttpException) {
MediatorResult.Error(e)
}
}
}
LoadType.PREPEND和LoadType.APPEND不断的呼唤!
在测试了整个代码之后,我终于找到了发生这种情况的原因。
问题出在“layout.xml”!你不应该把 RecyclerView 放在 NestedScrollView 中!!
但是为什么RecyclerView和NestedScrollView的bug没有完全解决呢?!
我正在使用 Android Paging 3,如您在 https://developer.android.com/topic/libraries/architecture/paging/v3-network-db 中所见。 当我 运行 应用程序 RemoteMediator 请求服务器获取列表,直到服务器上没有任何内容。
这里的重点是当用户到达列表底部时我们想要获取列表,但是 RemoteMediator 一直在请求直到获取服务器上的所有列表!
RemoteMediator.kt
@OptIn(ExperimentalPagingApi::class)
class ExampleRemoteMediator(
private val query: String,
private val database: RoomDb,
private val networkService: ExampleBackendService
) : RemoteMediator<Int, User>() {
val userDao = database.userDao()
val remoteKeyDao = database.remoteKeyDao()
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, User>
): MediatorResult {
return try {
// The network load method takes an optional String
// parameter. For every page after the first, pass the String
// token returned from the previous page to let it continue
// from where it left off. For REFRESH, pass null to load the
// first page.
val loadKey = when (loadType) {
LoadType.REFRESH -> null
// In this example, you never need to prepend, since REFRESH
// will always load the first page in the list. Immediately
// return, reporting end of pagination.
LoadType.PREPEND -> return MediatorResult.Success(
endOfPaginationReached = true
)
// Query remoteKeyDao for the next RemoteKey.
LoadType.APPEND -> {
val remoteKey = database.withTransaction {
remoteKeyDao.remoteKeyByQuery(query)
}
// You must explicitly check if the page key is null when
// appending, since null is only valid for initial load.
// If you receive null for APPEND, that means you have
// reached the end of pagination and there are no more
// items to load.
if (remoteKey.nextKey == null) {
return MediatorResult.Success(
endOfPaginationReached = true
)
}
remoteKey.nextKey
}
}
// Suspending network load via Retrofit. This doesn't need to
// be wrapped in a withContext(Dispatcher.IO) { ... } block
// since Retrofit's Coroutine CallAdapter dispatches on a
// worker thread.
val response = networkService.searchUsers(query, loadKey)
// Store loaded data, and next key in transaction, so that
// they're always consistent.
database.withTransaction {
if (loadType == LoadType.REFRESH) {
remoteKeyDao.deleteByQuery(query)
userDao.deleteByQuery(query)
}
// Update RemoteKey for this query.
remoteKeyDao.insertOrReplace(
RemoteKey(query, response.nextKey)
)
// Insert new users into database, which invalidates the
// current PagingData, allowing Paging to present the updates
// in the DB.
userDao.insertAll(response.users)
}
MediatorResult.Success(
endOfPaginationReached = response.nextKey == null
)
} catch (e: IOException) {
MediatorResult.Error(e)
} catch (e: HttpException) {
MediatorResult.Error(e)
}
}
}
LoadType.PREPEND和LoadType.APPEND不断的呼唤!
在测试了整个代码之后,我终于找到了发生这种情况的原因。 问题出在“layout.xml”!你不应该把 RecyclerView 放在 NestedScrollView 中!! 但是为什么RecyclerView和NestedScrollView的bug没有完全解决呢?!