Status Update
Comments
du...@google.com <du...@google.com> #2
First off - thanks for filing an issue!
Unfortunately the only scenario where we're able to add the header on initial load is if it also returns null for prevKey
marking endOfPaginationReached in the PREPEND direction (otherwise we can't know to add a header there until PREPEND / another call to PagingSource.load() returns).
Can you check to see if you're setting prevKey
to null
in your PagingSource.load()
implementation during REFRESH
?
du...@google.com <du...@google.com> #3
Alternatively, for a header that doesn't need access to the first time (and can therefore be displayed before the first item int he list is known), you can try PagingDataAdapter.withLoadStateHeader
and override LoadStateAdapter.displayLoadStateAsItem
to display the header in your desired cases.
ed...@gmail.com <ed...@gmail.com> #4
Hello, i think we have a misunderstanding here.
Let me take the example from your codelab (
Is this hiding of the first separator on design ? If so, is there a simple way to change this behavior ?
Thanks for your time.
cc...@google.com <cc...@google.com> #5
It may be that Room's LegacyPagingSource will always return -1 as prevKey, then return an empty list, meaning the separator will always be missing.
Can you try forcing prevKey = null when a PositionalDataSource returns data at offset=0?
ed...@gmail.com <ed...@gmail.com> #6
Yes the prevKey is always set to null when data offset is 0, and i'm also only using the footer :
adapter.withLoadStateFooter( footer = LoadingStateAdapter { adapter.retry() } )
ch...@gmail.com <ch...@gmail.com> #7
du...@google.com <du...@google.com> #8
I haven't forgotten about this, but just have a long queue of things to look at first!
ed...@gmail.com <ed...@gmail.com> #9
no worries :) thanks for the update !
du...@google.com <du...@google.com> #10
To be clear, this is an issue when using RemoteMediator, Paging can't know if the items on initial load represent the initial page until RemoteMediator load finishes, so it defers adding the header until the remote load comes back and this is a feature request to make the deferring on headers / footers optional?
Also, is there specific reason why adapter.withLoadStateHeader
does not work for you, since setting a permanent header to always show via ConcatAdapter
seems to be what you're looking for?
ed...@gmail.com <ed...@gmail.com> #11
I'm sorry, i think we still don't understand each other on this topic. Let me rephrase it please :
I'm not using a loadStateHeader
, it's about the separators inserted in the flow by the viewModel. In the map operation on the resulting Flow
from the repository, if a separator is inserted before the first element of the flow provided by the RemoteMediator, the recyclerView will not scroll automatically to it after refresh is done, but instead to the first "real" item. This behavior is clearly visible in the codelab example for the Paging Library too. The user has to manually scroll down a little to reveal the first separator.
In my case, like in the Paging Library codelabs, my first separator displays informations that are linked to the values of the item fetched. So using a static loadStateHeader is not relevant in this case.
[Deleted User] <[Deleted User]> #12
I think using RemoteMediator is not the cause. I have the same problems when display data from PagingSource generated by Room without a RemoteMediator
du...@google.com <du...@google.com> #13
The PagingSource
implementation from Room emites an empty page to terminate loads, so the pages it returns are similar to:
REFRESH(data = [..], prevKey = 0, nextKey = data.size + 1)
PREPEND(data = [], prevKey = null, nextKey = 0)
In this case separators will wait for the PREPEND to mark end of pagination due to prevKey == null before prepending the header, this is the root cause for the bug from Room's implementation (which should be fixed, but seems to be a separate issue from
du...@google.com <du...@google.com> #14
I'm sorry, i think we still don't understand each other on this topic. Let me rephrase it please :
I'm not using a loadStateHeader, it's about the separators inserted in the flow by the viewModel. In the map operation on the resulting Flow from the repository, if a separator is inserted before the first element of the flow provided by the RemoteMediator, the recyclerView will not scroll automatically to it after refresh is done, but instead to the first "real" item. This behavior is clearly visible in the codelab example for the Paging Library too. The user has to manually scroll down a little to reveal the first separator.
In my case, like in the Paging Library codelabs, my first separator displays informations that are linked to the values of the item fetched. So using a static loadStateHeader is not relevant in this case.
Thanks for clarifying, so if I'm understanding correctly, your setup uses RemoteMediator
and a PaginSource
which returns a Page with prevKey == null
in the REFRESH load and you'd basically like a way to configure the separator behavior so that it is immediately returned with PagingSource
's result, without waiting for RemoteMediator
to return endOfPaginationReached
? The issue is that if your RemoteMediator fetches new items at the beginning of the list it will appear to insert items between the HEADER and the first item after invalidate, but it seems reasonable to make it configurable.
cc...@google.com <cc...@google.com> #15
Working on a fix to the Room issue - can fix that at the level of PositionalDataSource, instead of always emitting an empty page.
In general we should try to have all terminal loads report that fact immediately, instead of with a second load. That's easy to do with a single load from a PagingSource/PositionalDataSource, but more tricky when we want to check if a RemoteMediator supports prepend or not. To support that case properly, we'd need to delay dispatching the initial page until we ask the RemoteMediator if it has more data. Possibly we could make that work by awaiting the RemoteMediator prepend status with a small timeout before dispatching the initial page.
ap...@google.com <ap...@google.com> #16
Branch: androidx-master-dev
commit fc303ca613ced2ae46bf61009682fd9b1386c01f
Author: Chris Craik <ccraik@google.com>
Date: Wed Jul 08 11:37:00 2020
Return next/prevKey = null from PositionalDataSources
Test: ./gradlew paging:p-c:cC
Test: ./gradlew room:integration-tests:room-testapp:cC
Bug: 160257628
Relnote: "Room (and PositionalDataSource) PagingSources will now
display a leading separator as part of the first page, so the user
doesn't need to scroll to reveal it."
Change-Id: I6f747ebc0b823b146c39b925ce1d659913a50421
M paging/common/src/main/kotlin/androidx/paging/PositionalDataSource.kt
M paging/common/src/test/kotlin/androidx/paging/PositionalDataSourceTest.kt
cc...@google.com <cc...@google.com> #17
The above change is scheduled to go out with alpha03, and should fix cases using Room without a RemoteMediator, like the comment in #12
This is still open to track the RemoteMediator variant of this issue.
ch...@gmail.com <ch...@gmail.com> #18
du...@google.com <du...@google.com> #19
It's a separate fix as it requires Paging to respect endOfPaginationReached
from REFRESH
properly, although RemoteMediator
and PagingSource
loads are async, if RemoteMediator.load()
returns with success immediately, we should use that information to add the header earlier.
Fundamentally though, if you use RemoteMediator
I think we would still want to wait for both RemoteMediator
and PagingSource
to signal PREPEND
is done before adding the header.
ed...@gmail.com <ed...@gmail.com> #20
Hello, is the fix included in the Alpha-03 shipped recently ?
ed...@gmail.com <ed...@gmail.com> #22
Yes, i've tried it, but so far i'm still facing the issue.
du...@google.com <du...@google.com> #23
The fix in alpha03 only fixes it if you are not using RemoteMediator
, the fix to propagate endOfPaginationReached to immediately show header is still on going!
du...@google.com <du...@google.com> #24
I believe this has been fixed on both ends now, we support endOfPaginationReached being marked from both PagingSource end and RemoteMediator end, which should propagate - but source / remote loads can still race, so there is an open ticket here
Description
Component used: androidx.paging:paging-runtime
Version used: 3.0.0-alpha02
Devices/Android versions reproduced on: Motorola X (XT1092) / Android 9
A separator inserted before the first element in a data flow, it doesn't appear unless the recycler view is scrolled up to show it. Is this intentionnal ?