Status Update
Comments
ba...@gmail.com <ba...@gmail.com> #2
ni...@gmail.com <ni...@gmail.com> #3
Thanks for reporting this!
ba...@gmail.com <ba...@gmail.com> #4
Same here, any update? Stuck at alpha02 for a long time.
ni...@gmail.com <ni...@gmail.com> #5
A few notes:
- Should be using
viewLifecyclerOwner.lifecycleScope
instead of justlifecycleScope
in aFragment
. - Cancellation is happening as a result of the fragment automatically paging over when they are initially created / added to viewpager2 (this is expected as far as I can tell)
- Right now
RemoteMediator
kind of acts as a dumb callback wheneverPagingSource
runs out of items to load, soREFRESH
error doesn't prevent remotePREPEND
/APPEND
. It's not clear to me yet whether it should or if we should change guidance to just handleAPPEND
. This is due to us changing the behavior of Remote REFRESH after the codelab was produced, so I'm very sorry for that. REFRESH is meant to handle any init that needs to happen, technically the initial network page fetch happens as a result of running out of items on the APPEND side.
e.g., Here is a modified sample from the opening post / #1's repro project that fixes the issue:
PageKeyedRemoteMediator.kt
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, RedditPost>
): MediatorResult {
try {
// Get the closest item from PagingState that we want to load data around.
val loadKey = when (loadType) {
REFRESH -> {
db.withTransaction {
postDao.deleteBySubreddit(subredditName)
remoteKeyDao.deleteBySubreddit(subredditName)
}
return MediatorResult.Success(endOfPaginationReached = false)
}
PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
APPEND -> {
// Query DB for SubredditRemoteKey for the subreddit.
// SubredditRemoteKey is a wrapper object we use to keep track of page keys we
// receive from the Reddit API to fetch the next or previous page.
val remoteKey = db.withTransaction {
remoteKeyDao.remoteKeyByPost(subredditName)
}
when {
remoteKey == null -> null
// We must explicitly check if the page key is null after initial load, since the
// Reddit API informs the end of the list by returning null for page key, but
// passing a null key to Reddit API will fetch the initial page.
remoteKey.nextPageKey == null -> {
return MediatorResult.Success(endOfPaginationReached = true)
}
else -> remoteKey.nextPageKey
}
}
}
val data = redditApi.getTop(
subreddit = subredditName,
after = loadKey,
before = null,
limit = state.config.pageSize * 3
).data
val items = data.children.map { it.data }
db.withTransaction {
remoteKeyDao.insert(SubredditRemoteKey(subredditName, data.after))
postDao.insertAll(items)
}
return MediatorResult.Success(endOfPaginationReached = items.isEmpty())
} catch (e: IOException) {
return MediatorResult.Error(e)
} catch (e: HttpException) {
return MediatorResult.Error(e)
} catch (e: CancellationException) {
Log.d("RemoteMediator","$subredditName $loadType canceled")
throw e
}
}
lo...@gmail.com <lo...@gmail.com> #6
Will keep this bug open to track the decision on blocking RemoteMediator
PREPEND
/ APPEND
after remote REFRESH error and any possible updates to the Codelab / Github samples.
The inconvenience of blocking on REFRESH is going to surface via needing to call retry()
, but it's possible there's something better we can do to handle cancellation more gracefully since we don't want to keep creating new PagingData
and also support loading in the background. (the thing to change to control this is when you start collecting from Pager.flow
, and the scope collection happens in).
lo...@gmail.com <lo...@gmail.com> #7
I have a question about the modified sample. Shouldn't deleteByXXX
be moved to after redditApi
execute successfully?
The UI side will see blink twice in this sample: Show db cache first then disappeared, show data again after redditApi
successful and insert data. The user experience is pretty bad.
Description
Hi, I have been struggling with this for some time and finally decided to post there to make sure it is not me doing something wrong.
Please see attached POC, screen recording and sample crash log in the attached file. Project is created with Android Studio Koala Feature Drop | 2024.1.2 Canary 5
Issue:
Attached project demonstrates crash with a Room database but I use custom
PagingSource
because I also use Paging 3 with content providers such as call log and contacts.Due to my my project's needs, I need to invalidate
PagingSource
from outside every now and then. One of the reasons for that is inserting adverts to certain locations.I created
Invalidator
interface whichInvalidatingPagingSource
that extendsPagingSource
uses.InvalidatingPagingSource
in return extended by my custom paging source andViewModel
is provided with an instance ofInvalidator
so it can callInvalidator.invalidateNow()
when it needs to invalidate the paging source.This setup works fine when data is on screen and no scrolling is being done. However, if invalidation happens while user is scrolling app crashes with
I am not sure if I am being thick but, when I check the source of tryGetViewHolderForPositionByDeadline I see that it does these checks:
According to log however,
position 115(offset:115)
falls in tostate:207
so crash should not happen. What am I missing?Notes: