Reputation: 2158
I'm using latest Jetpack libraries.
Pagination3 version: 3.0.0-alpha05
Room Version : 2.3.0-alpha02
My entities have Long as PrimaryKey
and Room can generate PagingSource
for other than Int
type.
error: For now, Room only supports PagingSource with Key of type Int.
public abstract androidx.paging.PagingSource<java.lang.Long, com.example.myEntity>` getPagingSource();
Therefore I tried to implement my custom PagingSource
, like docs suggest.
The problem is Data Refresh, since Room's generated code handles data refresh and with my code I'm not being able to handle this scenario.
Any suggestions how to implement custom PagingSource
for Room
that also handles Data Refresh
?
Upvotes: 11
Views: 7417
Reputation: 1175
Since you have 'refresh' scenario and using Room db, I am guessing you are using Paging3 with network+local db pattern(with Room db as local cache).
I had a similar situation with network + local db pattern. I am not sure if I understand your question correctly, or your situation is the same as the one I had, but I'll share what I did anyway.
What I was using:
What I did was let Room library to create PagingSource (with the key of Int
), and let RemoteMediator handle all the other cases, such as fetching the data from network when refreshing and/or appending, and inserting them into db right after fetch success.
My dao
function for creating PagingSource from Room Library:
@Query("SELECT * FROM article WHERE isUnread = 1")
fun getUnreadPagingSource(): PagingSource<Int, LocalArticle>
In my case I defined Repository class to have dao
class in its constructor to call the function above from repository when creating Pager class.
My custom RemoteMediator class looks something like this below:
RemoteMediator#load
function always returns true
when the value of the argument loadType
is LoadType.PREPEND
.class FeedMediator(
private val repository: FeedRepository
) : RemoteMediator<Int, LocalArticle>() {
...
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, LocalArticle>
): MediatorResult = runCatching {
when (loadType) {
LoadType.PREPEND -> true
LoadType.REFRESH -> {
feedRepository.refresh()
false
}
LoadType.APPEND -> {
val continuation = feedRepository.continuation()
if (continuation.isNullOrEmpty()) {
true
} else {
loadFeedAndCheckContinuation(continuation)
}
}
}
}.fold(
onSuccess = { endOfPaginationReached -> MediatorResult.Success(endOfPaginationReached) },
onFailure = {
Timber.e(it)
MediatorResult.Error(it)
}
)
private suspend fun loadFeedAndCheckContinuation(continuation: String?): Boolean {
val feed = feedRepository.load(continuation)
feedRepository.insert(feed)
return feed.continuation.isNullOrEmpty()
}
Finally you can create Pager
class.
fun createFeedPager(
mediator: FeedMediator<Int, LocalArticle>,
repository: FeedRepository
) = Pager(
config = PagingConfig(
pageSize = FETCH_FEED_COUNT,
enablePlaceholders = false,
prefetchDistance = PREFETCH_DISTANCE
),
remoteMediator = mediator,
pagingSourceFactory = { repository.getUnreadPagingSource() }
)
I hope it helps in some way..
Other references:
EDIT: After reading the doc again, I found a statement where the doc clearly states:
RemoteMediator to use for loading the data from the network into the local database.
Upvotes: -3