Search code examples
androidkotlinandroid-jetpack-composeandroid-paging-3

RemoteMediator doesn't go next page, paging 3 problem


i have a problem in my Jetpack Compose project. I want to setup a RemoteMediator, with nextPage and PrevPage but this doesn't work properly, it doesn't show me the next page. Thing to know, i d'ont have ani "id" key in my Json so i'm using phone number to create unique keys.

This is my code 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)
        }
}

}


Solution

  • i've found the solution.

    I added this at the top of RemoteMediator ->

    override suspend fun initialize(): InitializeAction {
        return InitializeAction.LAUNCH_INITIAL_REFRESH
    }
    

    After, i initialized the prevPage and NextPage in LocalDb transaction.

    I finished by adding suspend to all 3 function getRemoteKy at the end and on MediatorKeyDao function.