I have used Jetpack's Paging 3 library in my project for handling data pagination. I have a use case which when user changes something in search request (for example adding/removing some filters), I have to call API and repopulate my list with new data based on the new search request. But when I create the new Pager
instance and pass it to my PagingDataAdapter
adapter, it throws:
java.lang.IllegalStateException: Collecting from multiple PagingData concurrently is an illegal operation.
My implementation is like this:
Repository
class Repository {
fun getDataStream(request: Request): Flow<PagingData<Response>> {
return Pager(
config = PagingConfig(
pageSize = 10,
initialLoadSize = 10,
prefetchDistance = 3
),
initialKey = 1,
pagingSourceFactory = {
DataPagingSource(
request = request,
repository = this
)
}
).flow
}
fun getData(page: Int, request: Request): Result<Response> {
return remoteDataSource.getData(page, request)
}
}
DataPagingSource
class DataPagingSource(
private val request: Request,
private val repository: Repository
) : PagingSource<Int, Response>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Response> {
val page = params.key ?: 1
// Result is a sealed class which has two derived classes: Success and Error
return when (val result = repository.getData(page, request)) {
is Result.Success -> {
LoadResult.Page(
data = result.data,
nextKey = page.inc(),
prevKey = null
)
}
is Result.Error -> LoadResult.Error(
result.error
)
}
}
}
ViewModel
class SomeViewModel(
private val repository: Repository
): ViewModel() {
private val _currentRequest = MutableLiveData<Request>()
val data = _currentRequest
.switchMap {
repository
.getDataStream(it)
.cachedIn(viewModelScope)
.asLiveData()
}
fun updateRequest(request: Request) {
_currentRequest.postValue(request)
}
}
Fragment
class SomeFragment: Fragment() {
private lateinit var viewModel: SomeViewModel
// ...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// ...
viewModel.data.observe(
viewLifecycleOwner,
Observer {
lifecycleScope.launch {
adapter.submitData(it)
}
}
)
}
// ...
}
It would be great if someone help fix this problem.
Thank you
submitList
. Thanks for the hints. – Celerity