Charlie Wu
Charlie Wu

Reputation: 7757

Android Paging 3 with Room

I'm migrating from Paging 2 to Paging 3. The app stores a large dataset in a database using Room, and I can load the data from Room and display it okay. The issue I have is as soon as the app makes a change to the database, it crashes.

Code Snippets
IssueRepository

@Query("SELECT * FROM isssue WHERE project_id = ?")
fun findAllInProject(projectId:Int): PagingSource<Int, IssueListBean>

In the function onCreateView

val dataSource = DB.store.issueRepository().findAllInProject(project.id)
val pageConfig = PagingConfig(50)
val pager = Pager(pageConfig, null) { dataSource }.flow
viewLifecycleOwner.lifecycleScope.launchWhenCreated {
    pager.collectLatest { data ->
        adapter.submitData(data)
    }
}
class PagingAdapter : PagingDataAdapter<IssueListBean, PagingAdapter.ViewHolder>(EntityComparator()) {
    inner class ViewHolder(private val adapterBinding: ItemIssueListBinding) : RecyclerView.ViewHolder(adapterBinding.root) {
        fun bind(position: Int) {
            val issueListBean = getItem(position)
            adapterBinding.label.text = issueListBean.label
        }
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = ItemIssueListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(position)
    }
}

So when users tap on an item they can edit it. As soon the item is saved via Room the app crashes with the following exception:

java.lang.IllegalStateException: An instance of PagingSource was re-used when Pager expected to create a new
    instance. Ensure that the pagingSourceFactory passed to Pager always returns a
    new instance of PagingSource.

Am I using Paging 3 wrong? I can't find many articles online talk about using Room as data source where you make changes.

Upvotes: 5

Views: 4353

Answers (1)

Angus H
Angus H

Reputation: 408

The lambda you pass to Pager() should return a new instance of the data source each time, so move the call to findAllInProject() into that lambda, like

val pager = Pager(pageConfig, null) {
    DB.store.issueRepository().findAllInProject(project.id)
}.flow

Upvotes: 3

Related Questions