Status Update
Comments
rf...@gmail.com <rf...@gmail.com> #2
tn...@google.com <tn...@google.com> #3
Thanks for reporting this!
vs...@google.com <vs...@google.com> #4
Same here, any update? Stuck at alpha02 for a long time.
[Deleted User] <[Deleted User]> #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
}
}
vs...@google.com <vs...@google.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).
[Deleted User] <[Deleted User]> #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.
[Deleted User] <[Deleted User]> #8
To be clear the above sample is a workaround a deeper issue in Paging which isn't handling cancellation gracefully due to Remote REFRESH errors not blocking remote PREPEND / APPEND.
[Deleted User] <[Deleted User]> #9
I found that if using fragment.lifecycleScope.launchWhenResume to collect each page data then it will work normally. ViewPager2 FragmentStatePager will move fragment to onResume/onPause.
[Deleted User] <[Deleted User]> #10
Good to hear, I think we can still do a better job of handling cancellation and propagating remote state, e.g., if you have many pages in viewpager and flip back and forth I think you'll still eventually get stuck, since the collector on PagingData will get canceled and there's no invalidate signal to restart it without manually calling adapter.refresh()
.
tn...@google.com <tn...@google.com> #11
Branch: androidx-master-dev
commit c97e21810e49b3f8043c8d7c3951b16e8b38e6db
Author: Yigit Boyar <yboyar@google.com>
Date: Fri Oct 16 10:39:22 2020
Add priority to single runner
This CL adds ability to accept priority to SingleRunner.
It will be necessary for the new remote mediator implementation
where it will rely on single runner to cancel lower priority
requests.
Bug: 162252536
Test: SingleRunnerTest
Change-Id: I01351ac385b252f80ab6079d42f2cf0edf8d6667
M paging/common/src/main/kotlin/androidx/paging/SingleRunner.kt
M paging/common/src/test/kotlin/androidx/paging/SingleRunnerTest.kt
jl...@gmail.com <jl...@gmail.com> #12
Branch: androidx-master-dev
commit f86129d60bb33243d06837291f0e2bd0f26f4bd3
Author: Yigit Boyar <yboyar@google.com>
Date: Fri Oct 09 11:34:07 2020
RemoteMediatorAccessor Refactor
This CL changes how remote mediator and snapshots interact.
Previously, all calls to remote mediator were done in a
snapshot's scope and snapshot was also responsible to track
load states.
It created a problem where remote mediator calls would be
cancelled when snapshot is replaced by a newer one. It also
made the load state logic fairly complicated in PageFetcherSnapshot.
This CL de-couples the two as much as possible.
With this change, RemoteMediatorAcccessor uses the scope of
the `Pager.flow` collection instead of the scope from the
PageFetcherSnapshot. PageFetcherSnapshot is now only responsible
to send events to the accessor when it needs more data.
RemoteMediatorAccessor manages its own loading state.
We still need some syncronization between the two to ensure certain
load events are not dispatched before data is loaded (e.g. after a
pull to refresh, you don't want refresh state to go idle before the
new local data is loaded for UI consistency). This logic is now
handled by the PageFetcher where it appends the load states to each
insert page and for other events (loading, error), directly sends them
to the downstream.
Bug: 162252536
Test: RemoteMediatorAccessorTest, PageFetcherSnapshotTest
Relnote: "Paging will no longer cancel a `RemoteMediator#load` call
due to a page invalidation. It will also no longer make an
append/prepend load request, *if REFRESH is required*, until REFRESH
request completes successfully."
Change-Id: I6390be0c0c1073005456f928a2a8afa81c16d3ef
M paging/common/api/current.txt
M paging/common/api/public_plus_experimental_current.txt
M paging/common/api/restricted_current.txt
M paging/common/src/main/kotlin/androidx/paging/CachedPageEventFlow.kt
M paging/common/src/main/kotlin/androidx/paging/LoadStates.kt
M paging/common/src/main/kotlin/androidx/paging/MutableLoadStateCollection.kt
M paging/common/src/main/kotlin/androidx/paging/PageEvent.kt
M paging/common/src/main/kotlin/androidx/paging/PageFetcher.kt
M paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
M paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshotState.kt
M paging/common/src/main/kotlin/androidx/paging/PagingDataDiffer.kt
M paging/common/src/main/kotlin/androidx/paging/RemoteMediator.kt
M paging/common/src/main/kotlin/androidx/paging/RemoteMediatorAccessor.kt
M paging/common/src/test/kotlin/androidx/paging/PageEventTest.kt
M paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotStateTest.kt
M paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
M paging/common/src/test/kotlin/androidx/paging/RemoteMediatorAccessorTest.kt
M testutils/testutils-paging/src/main/java/androidx/paging/RemoteMediatorMock.kt
tn...@google.com <tn...@google.com> #13
There is for sure a bug in locale handling of floats; I submitted a fix for that last week, and I've backported it to 21.0.1. However, it sounds like there's also something going on with IntelliJ; the author of the device class said on adt-dev that it will ignore the contents if it can't parse it (
If there's a separate issue with IntelliJ can somebody verify and file a new issue after testing with 21.0.1 to separate it from the locale issue?
[Deleted User] <[Deleted User]> #14
am...@gmail.com <am...@gmail.com> #15
do it here
tn...@google.com <tn...@google.com> #16
ke...@gmail.com <ke...@gmail.com> #17
It appears Eclipse rejects devices.xml because it doesn't comply with it's XSD, not because it is not usable. Apparently the others don't check and use it (successfully) anyway.
I had to make two changes to make mine parse correctly in Eclipse (and to work for running apps).
I changed 400dpi to xxhdpi in
<d:pixel-density>400dpi</d:pixel-density>
and I deleted lines like:
<d:skin>C:/Android/platforms/android-19/skins/GalaxyS5</d:skin>
These are apparently not allowed by the XSD.
Note that this is what worked for me. In general the problem seems to be that Android Studio is writing devices.xml files that are invalid for the specified XSD, and Eclipse is renaming the file, so it doesn't work, when it doesn't parse correctly.
de...@gmail.com <de...@gmail.com> #18
zi...@gmail.com <zi...@gmail.com> #19
With <d:pixel-density>280dpi</d:pixel-density> AVD Manager/Android Studio renames devices.xml to .old; if I change manually in the xml file 280dpi to 400dpi, all works OK.
Please, check the parser and fix it.
Description
applicable)
Host OS: Ubuntu Lucid
SDK tools version (available in the "About" section of the 'android' tool
UI): 21
Eclipse version: Juno SR 1 Build ID 20121004-1855
ADT plug-in version: 21.0.0.v201210310015-519525
STEPS TO REPRODUCE:
1. ensure you have the file devices.xml in $HOME/.android with some device layouts configured
2. start Eclipse and open an Android project
3. open a layout XML in the layout editor
EXPECTED RESULTS:
the file $HOME/.android/devices.xml is kept
OBSERVED RESULTS:
the file $HOME/.android/devices.xml is deleted
ADDITIONAL INFORMATION:
The Android layout preview of IntelliJ IDEA 11 relies on the file $HOME/.android/devices.xml .
So basically since the JellyBean 4.2 ADT update opening a layout file in Eclipse now breaks the layout preview in IntelliJ.
As a workaround I have to back-up devices.xml and copy it back each time the Eclipse ADT layout edtior deleted it.