I am following this example to implement the paging library, using the TMDB Api.
As I scroll down the list reaching a boundary condition, it will always scroll back up to page 1.
I think there is some issues going on with the RemoteMediator class causing this issue, but I am almost copying from the Google example...
Below is my log. I am scrolling down the list here.
I guess the problem is that "LoadType = PREPEND" is called as I scroll down the list. The adapter first APPEND the next page, but then detects a boundary condition at the top of the next page and decide to do a PREPEND, which cause the issue? I am not sure how to solve this issue. I have tried changing the config of the pager, but it doesn't work.
You may find my code here.
Thanks in advance!
I had the same problem, but for me the solution was removing the following lines from the SearchRepositoriesActivity:
private fun initSearch(query: String) {
/* Some code here */
// Remove these lines
/*
lifecycleScope.launch {
@OptIn(ExperimentalPagingApi::class)
adapter.dataRefreshFlow.collect {
binding.list.scrollToPosition(0)
}
}
*/
}
You can see it here on the repository. This was introduced in the codelab so that the RecyclerView scrolled back to the top once a request (for a new repository search) is completed, which was exactly what was happening with me: The RecyclerView only went up after the OkHttp logged that it received the result from the request.
I can't understand completely why this was working with the network only implementation, but not with the network + database. If I understand the code correctly, this stream should only be notified when an LoadState.REFRESH event happens. I believe there's a hidden LoadState.REFRESH that's being sent but it's not received on the RemoteMediator. Once I removed the code above, the screen still flickers because it moves to a Loading state really quickly. You can see it by adding a Log to the addLoadStateListener (available here) like so:
adapter.addLoadStateListener { loadState ->
// Add this log
Log.d("UI_PAGING", "source: ${loadState.source.refresh}, remote: ${loadState.refresh}")
// Only show the list if refresh succeeds.
binding.list.isVisible = loadState.source.refresh is LoadState.NotLoading
// Show loading spinner during initial load or refresh
binding.progressBar.isVisible = loadState.source.refresh is LoadState.Loading
// Show the retry state if initial load or refresh fails.
binding.retryButton.isVisible = loadState.source.refresh is LoadState.Error
/* some other code here */
}
which shows the following logs:

As you can see Room is changing the refresh state once the append happens.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With