I'm using the Paging 3.0 library to load some data from the server and I'm currently facing an issue where the server returns small number of items i.e 1,2, items. What happens now is the Paging library keeps calling the same endpoint, non-stop. My issue is similar to question 1 and I guess 2 just that mine is with Paging 3.0 and the approach is different.

This is my PagingSource:
private const val STARTING_PAGE_INDEX = 0
class MyPagingSource(
private val apiService: MyProductService,
private val query: String
) : PagingSource<Int, ProductResponse>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ProductResponse> {
val position = params.key ?: STARTING_PAGE_INDEX
return try {
val response = apiService.searchProduct(STARTING_PAGE_INDEX, query, params.loadSize)
val products = response.data?.records ?: emptyList()
LoadResult.Page(
data = products,
prevKey = if (position == STARTING_PAGE_INDEX) null else position - 1,
nextKey = if (products.isEmpty()) null else position + 1
)
}catch (exception: IOException){
return LoadResult.Error(exception)
}catch (exception: HttpException) {
return LoadResult.Error(exception)
}
}
}
The PagingConfig:
override fun searchProduct(
product: String
): Flow<PagingData<ProductResponse>> {
return Pager(
config = PagingConfig(
pageSize = RECORDS_PER_PAGE,
enablePlaceholders = false,
maxSize = MAX_RECORDS_PER_PAGE
),
pagingSourceFactory = { MyPagingSource(apiService, product) }
).flow
}
companion object {
private const val RECORDS_PER_PAGE = 6
private const val MAX_RECORDS_PER_PAGE = 20
}
In my ViewModel, I have this:
private var currentQueryValue: String? = null
private var currentSearchResult: UIEvent<Flow<PagingData<ProductResponse>>>? = null
fun searchProduct(query: String): UIEvent<Flow<PagingData<ProductResponse>>> {
val lastResult = currentSearchResult
if (query == currentQueryValue && lastResult != null) {
return lastResult
}
currentQueryValue = query
val newResult: Flow<PagingData<ProductResponse>> = dataSource.searchProduct(query)
.cachedIn(viewModelScope)
currentSearchResult = UIEvent(newResult)
return UIEvent(newResult)
}
And in the Fragment, I have this:
private var searchProductJob: Job? = null
private val viewModel by viewModels<MyViewModel> { viewModelProviderFactory }
....
private fun searchProduct(queryString: String) {
searchProductJob?.cancel()
searchProductJob = lifecycleScope.launch {
viewModel.searchProduct(queryString.trim().toLowerCase(Locale.getDefault()))
.getContentIfNotHandled()?.let { pagingData ->
pagingData.collectLatest {
productResultAdapter.submitData(it)
search_product_recycler_view.scrollToPosition(0)
}
}
}
}
I would appreciate any suggestions on how to go about this :)