Status Update
Comments
ys...@google.com <ys...@google.com> #3
Also adding that I notice a crash while repro-ing this:
2021-01-25 11:47:32.315 17990-17990/paging.android.example.com.pagingsample E/AndroidRuntime: FATAL EXCEPTION: main
Process: paging.android.example.com.pagingsample, PID: 17990
java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
at java.util.ArrayList.get(ArrayList.java:437)
at androidx.paging.PageFetcherSnapshot.doLoad(PageFetcherSnapshot.kt:370)
at androidx.paging.PageFetcherSnapshot$collectAsGenerationalViewportHints$$inlined$collect$1.emit(Collect.kt:133)
at kotlinx.coroutines.flow.FlowKt__ChannelsKt.emitAllImpl$FlowKt__ChannelsKt(Channels.kt:61)
at kotlinx.coroutines.flow.FlowKt__ChannelsKt$emitAllImpl$1.invokeSuspend(Unknown Source:11)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7660)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2021-01-25 11:47:32.501 14519-14615/com.google.android.googlequicksearchbox E/MDD: DownloadProgressMonitor: Can't find file for uri: android://com.google.android.googlequicksearchbox/files/sharedminusonemodule/shared/SharedMinusOneData.pb.tmp
2021-01-25 11:48:08.376 2197-9975/com.android.phone E/PhoneInterfaceManager: [PhoneIntfMgr] getCarrierPrivilegeStatus: Invalid subId
2021-01-25 11:48:28.470 914-914/? E/BatteryDefender: Failed to read /sys/class/power_supply/wireless/online
ys...@google.com <ys...@google.com> #4
For #3, filed separately here:
cl...@google.com <cl...@google.com> #5
Hmm so I thought about this for awhile and it seems quite difficult to solve - essentially what is happening is we are prepending more items than there are number of placeholders due to the addition of separators, so it's impossible to scroll to the top before prepending because we don't know how many items to scroll up by. Basically the placeholders don't map 1:1 to the original item, so we have to decide how and where to notify RV that there are extra items and the current behavior for prepend is to always send the onInserted event to notify new items above the current position to handle the regular scrolling via swipe scenario.
In the swipe scroll case, user wants to see the bottom items from prepended page first, and then have extra items added above the scroll position, but in the scroll to top case we want to see the top items first, and then add extra items to the bottom. Since scrollToPosition always puts the desired index to position at the top, we need some way to tell paging that if we prepend due to call to scrollToPosition, we basically need to switch the order of the differ events to work like append instead.
As a simple workaround, you can set jumpThreshold
in PagingConfig
to be the same as maxSize
, and this will cause paging to use the refresh / invalidate flow to load from the scrollToPosition index (which is what you want anyway in large jumps instead of prepending until you get there).
ap...@google.com <ap...@google.com> #6
Maybe there's another way to look at this. Is there a way to 'reset' the RecyclerView, the PagingDataAdapter and PagingSource that's coming from Room, so that they ignore anything that's happened up to now (any scrolling or loading different pages from the db), and behave as if they've just been bound for the first time again?
ap...@google.com <ap...@google.com> #7
I'm afraid this is also hard for recyclerview (both both smooth and non-smooth scroll).
Basically, when you try to scroll to a position, recyclerview just lays out in that position. but if paging adds more items above, that happens after RecyclerView scrolls. The same thing happens if you try to scroll to a non-existing position (e.g. you only have 50 in memory and you scroll to 100) It will just stop 50.
Due to the nature of this problem (not knowing when data will stop coming), a possible solution is to actually write a custom scroller over recyclerview that keeps pushing it to 0 as items are loaded.
For jump scenerios, it might be even better to just get a new paging flow that starts w/o an initial key and also set a new adapter on the recyclerview (so that it does not try to diff). If you use the same adapter, you can consider calling notifyDataSetChanged when list is updated on the adapter, that should fool RecyclerView to just render from scratch.
cl...@google.com <cl...@google.com> #8
cl...@google.com <cl...@google.com> #9
Without stable list, jumping won't really be feasible. I think the only way it can work is to create a new pager w/ an initial key to restart the data from that location (combined w/ scrollToPosition(0) )
na...@google.com <na...@google.com> #10
While playing with my workaround I noticed it only works in some cases and as there is a separate bug causing multiple jumps to happen on scroll to top. This is why it ends up scrolling downwards after jumping to the top due to jumping.
I believe the root cause is due to conflated hints causing new generation to reload a second time.
Description
Version used:
androidx.paging:paging-runtime:3.1.1
androidx.paging:paging-compose:1.0.0-alpha17
Devices/Android versions reproduced on: n/a
I'm trying to use the Paging 3 library for my Wear OS app, but I am unable to put the LazyPagingItems from my Pager implementation on a ScalingLazyColumn in the UI. I notice that you are able to do this for LazyColumn, but not for ScalingLazyColumn. Are there plans for ScalingLazyColumn to support LazyPagingItems?