'Android Paging 3: LoadType.APPEND returns null remote keys
I've been trying to work out how to fix my issue with RemoteMediator
's APPEND
LoadType
.
On an empty Room DB, here's how the LoadType
flows:
REFRESH -> PREPEND -> APPEND (remoteKeys = null, endOfPaginationReached = true)
With at least 10 rows for entity and remote keys table, here's how the LoadType
flows:
REFRESH -> PREPEND -> APPEND (remoteKeys = prev=null, next=2, endOfPaginationReached = false)
Clearly, my issue is on a fresh installed device (with empty Room DB), the user won't see more than 10 items because APPEND
's state.lastItemOrNull()
is returning null
.
Here's my code so far:
private suspend fun getRemoteKeysForLastItem(state: PagingState<Int, MovieCache>): MovieRemoteKeys? {
return state.lastItemOrNull()?.let { movie ->
appDatabase.withTransaction {
appDatabase.remoteKeysDao().remoteKeysByImdbId(movie.imdbId)
}
}
}
for my load()
function:
val loadKey = when (loadType) {
LoadType.REFRESH -> {
val key = getRemoteKeysClosestToCurrentPosition(state)
Timber.d("REFRESH key: $key, output: ${key?.nextKey?.minus(1)}")
key?.nextKey?.minus(1) ?: 1
}
LoadType.PREPEND -> {
Timber.d("PREPEND key requested")
return MediatorResult.Success(true)
}
LoadType.APPEND -> {
val key = getRemoteKeysForLastItem(state)
Timber.d("APPEND key: $key")
appDatabase.withTransaction {
val size = movieDao.movies().size
val remoteSize = remoteKeysDao.allKeys().size
Timber.d("APPEND DB size: $size, remote: $remoteSize")
}
key?.nextKey ?: return MediatorResult.Success(true)
}
}
Here's a sample logcat showing that APPEND
is null
Leaving my app unable to scroll down even at least once!
Solution 1:[1]
Finally, this is how I managed to fix this issue, by relying on the remoteKeys on the DB than PagingState
:
LoadType.APPEND -> {
// val key = getRemoteKeysForLastItem(state) // Doesn't work. state returns NULL even Room has data for both remote keys and entity.
val key = appDatabase.withTransaction {
remoteKeysDao.allKeys().lastOrNull() // Workaround
}
key?.nextKey ?: return MediatorResult.Success(true)
}
Solution 2:[2]
Instead of returning endOfPaginationReached = true
from LoadType.APPEND when remote key is null
, return endOfPaginationReached = key != null
. Returning endOfPaginationReached = false
means keep loading which will give you the remote key next time.
LoadType.APPEND -> {
val key = getRemoteKeysForLastItem(state)
Timber.d("APPEND key: $key")
appDatabase.withTransaction {
val size = movieDao.movies().size
val remoteSize = remoteKeysDao.allKeys().size
Timber.d("APPEND DB size: $size, remote: $remoteSize")
}
key?.nextKey ?: return MediatorResult.Success(key != null)
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Jim Ovejera |
Solution 2 | Md. Asaduzzaman |