RemoteMediator 不转到下一页,分页 3 问题
RemoteMediator doesn't go next page, paging 3 problem
我的 Jetpack Compose 项目有问题。
我想设置一个带有 nextPage 和 PrevPage 的 RemoteMediator,但这不能正常工作,它不显示下一页。
需要注意的是,我的 Json 中没有“id”键,所以我使用 phone 数字来创建唯一键。
这是我的代码
RemoteMediator.kt
@OptIn(ExperimentalPagingApi::class)
class RemoteMediator @Inject constructor(
private val dataDb: DataDb,
private val retrofitService: RetrofitService,
) : RemoteMediator<Int, com.example.testlydiaapp.data.online.model.Result>() {
val dataDao = dataDb.dataDao()
val randomUserKeysDao = dataDb.randomUserKeysDao()
override suspend fun load(loadType: LoadType, state: PagingState<Int, com.example.testlydiaapp.data.online.model.Result>): MediatorResult {
return try {
val currentPage = when (loadType) {
LoadType.REFRESH -> {
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state = state)
remoteKeys?.nextPage?.minus(1) ?: 1
}
LoadType.PREPEND -> {
val remoteKeys = getRemoteKeyForFirstTime(state = state)
val prevPage = remoteKeys?.prevPage
?: return MediatorResult.Success(
endOfPaginationReached = remoteKeys != null
)
prevPage
}
LoadType.APPEND -> {
val remoteKeys = getRemoteKeyForLastTime(state = state)
val nextPage = remoteKeys?.nextPage
?: return MediatorResult.Success(
endOfPaginationReached = remoteKeys != null
)
nextPage
}
}
val response = retrofitService.getRandomUsers(page = currentPage)
val endOfPaginationReached = response.results.isEmpty()
val prevPage = if (currentPage == 1) null else currentPage - 1
val nextPage = if (endOfPaginationReached) null else currentPage + 1
dataDb.withTransaction {
if (loadType == LoadType.REFRESH) {
dataDao.clearAll()
randomUserKeysDao.clearAllRandomUsersRemoteKeys()
}
val keys = response.results.map { randomUser ->
RandomUsersRemoteKeys(
id = randomUser.phone,
prevPage = prevPage,
nextPage = nextPage
)
}
randomUserKeysDao.insertAllRandomUsersRemoteKeys(remoteKeys = keys)
dataDao.insertRandomUserList(item = response.results)
}
MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
} catch (e: Exception) {
return MediatorResult.Error(e)
}
}
private fun getRemoteKeyClosestToCurrentPosition(
state: PagingState<Int, com.example.testlydiaapp.data.online.model.Result>
): RandomUsersRemoteKeys? {
return state.anchorPosition?.let {
state.closestItemToPosition(it)?.phone?.let { id ->
randomUserKeysDao.getRandomUsersRemoteKeys(id = id)
}
}
}
private fun getRemoteKeyForFirstTime(
state: PagingState<Int, com.example.testlydiaapp.data.online.model.Result>
): RandomUsersRemoteKeys? {
return state.pages.firstOrNull() { it.data.isNotEmpty() }?.data?.firstOrNull()
?.let {
randomUserKeysDao.getRandomUsersRemoteKeys(id = it.phone)
}
}
private fun getRemoteKeyForLastTime(
state: PagingState<Int, com.example.testlydiaapp.data.online.model.Result>
): RandomUsersRemoteKeys? {
return state.pages.lastOrNull() { it.data.isNotEmpty() }?.data?.lastOrNull()
?.let {
randomUserKeysDao.getRandomUsersRemoteKeys(id = it.phone)
}
}
}
我找到了解决方案。
我在 RemoteMediator 的顶部添加了这个 ->
override suspend fun initialize(): InitializeAction {
return InitializeAction.LAUNCH_INITIAL_REFRESH
}
之后,我在 LocalDb 事务中初始化了 prevPage 和 NextPage。
我通过在末尾和 MediatorKeyDao 函数上向所有 3 个函数 getRemoteKy 添加挂起来完成。
我的 Jetpack Compose 项目有问题。 我想设置一个带有 nextPage 和 PrevPage 的 RemoteMediator,但这不能正常工作,它不显示下一页。 需要注意的是,我的 Json 中没有“id”键,所以我使用 phone 数字来创建唯一键。
这是我的代码 RemoteMediator.kt
@OptIn(ExperimentalPagingApi::class)
class RemoteMediator @Inject constructor(
private val dataDb: DataDb,
private val retrofitService: RetrofitService,
) : RemoteMediator<Int, com.example.testlydiaapp.data.online.model.Result>() {
val dataDao = dataDb.dataDao()
val randomUserKeysDao = dataDb.randomUserKeysDao()
override suspend fun load(loadType: LoadType, state: PagingState<Int, com.example.testlydiaapp.data.online.model.Result>): MediatorResult {
return try {
val currentPage = when (loadType) {
LoadType.REFRESH -> {
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state = state)
remoteKeys?.nextPage?.minus(1) ?: 1
}
LoadType.PREPEND -> {
val remoteKeys = getRemoteKeyForFirstTime(state = state)
val prevPage = remoteKeys?.prevPage
?: return MediatorResult.Success(
endOfPaginationReached = remoteKeys != null
)
prevPage
}
LoadType.APPEND -> {
val remoteKeys = getRemoteKeyForLastTime(state = state)
val nextPage = remoteKeys?.nextPage
?: return MediatorResult.Success(
endOfPaginationReached = remoteKeys != null
)
nextPage
}
}
val response = retrofitService.getRandomUsers(page = currentPage)
val endOfPaginationReached = response.results.isEmpty()
val prevPage = if (currentPage == 1) null else currentPage - 1
val nextPage = if (endOfPaginationReached) null else currentPage + 1
dataDb.withTransaction {
if (loadType == LoadType.REFRESH) {
dataDao.clearAll()
randomUserKeysDao.clearAllRandomUsersRemoteKeys()
}
val keys = response.results.map { randomUser ->
RandomUsersRemoteKeys(
id = randomUser.phone,
prevPage = prevPage,
nextPage = nextPage
)
}
randomUserKeysDao.insertAllRandomUsersRemoteKeys(remoteKeys = keys)
dataDao.insertRandomUserList(item = response.results)
}
MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
} catch (e: Exception) {
return MediatorResult.Error(e)
}
}
private fun getRemoteKeyClosestToCurrentPosition(
state: PagingState<Int, com.example.testlydiaapp.data.online.model.Result>
): RandomUsersRemoteKeys? {
return state.anchorPosition?.let {
state.closestItemToPosition(it)?.phone?.let { id ->
randomUserKeysDao.getRandomUsersRemoteKeys(id = id)
}
}
}
private fun getRemoteKeyForFirstTime(
state: PagingState<Int, com.example.testlydiaapp.data.online.model.Result>
): RandomUsersRemoteKeys? {
return state.pages.firstOrNull() { it.data.isNotEmpty() }?.data?.firstOrNull()
?.let {
randomUserKeysDao.getRandomUsersRemoteKeys(id = it.phone)
}
}
private fun getRemoteKeyForLastTime(
state: PagingState<Int, com.example.testlydiaapp.data.online.model.Result>
): RandomUsersRemoteKeys? {
return state.pages.lastOrNull() { it.data.isNotEmpty() }?.data?.lastOrNull()
?.let {
randomUserKeysDao.getRandomUsersRemoteKeys(id = it.phone)
}
}
}
我找到了解决方案。
我在 RemoteMediator 的顶部添加了这个 ->
override suspend fun initialize(): InitializeAction {
return InitializeAction.LAUNCH_INITIAL_REFRESH
}
之后,我在 LocalDb 事务中初始化了 prevPage 和 NextPage。
我通过在末尾和 MediatorKeyDao 函数上向所有 3 个函数 getRemoteKy 添加挂起来完成。