Reputation: 55
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.
Thanks in advance!
Upvotes: 3
Views: 2170
Reputation: 1
I have encountered the same problem, but I have found a solution. This should be because of the database index. Check the primary key of your entity class, which is generally the id, but the size of the id should be messy. When Room inserts the data, it will be inserted according to the size of the primary key, which causes your database and api The data order of the response is wrong.
The solution is to redefine another primary key in your entity class and let it grow automatically, like databaseId,so that the insertion order of the Room database is correct. This can solve the problem of list sliding
@Entity(tableName = "articles")
data class Article(
@PrimaryKey(autoGenerate = true)
val databaseId: Int,
@field:SerializedName("id")
val id: Int,
@field:SerializedName("title")
val title: String,
@field:SerializedName("apkLink")
val apkLink: String,
@field:SerializedName("audit")
val audit: Int
Upvotes: 0
Reputation: 822
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.
Upvotes: 2