How can I get pagingData whenever multiple parameters change?

40 views Asked by At

I'm using Paging3 library, and when I get data from the server, I'm importing it to PagingData via PagingSource.

It works well if no parameters are needed for API calls, like this:

class ProductPagingSource(
    private val productApi: ProductApi,
) : PagingSource<Int, ProductEntity>() {
    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ProductEntity> {
        try {
            val nextPageNumber = params.key ?: 1
            val response = productApi.getProduct(nextPageNumber)

            return if (response.isSuccessful) {
                val data = response.body()?.data
                val productList = data?.product ?: emptyList()

                LoadResult.Page(
                    data = productList,
                    prevKey = if (nextPageNumber == 1) null else nextPageNumber - 1,
                    nextKey = if (eventList.isEmpty()) null else nextPageNumber + 1,
                )
            } else {
                LoadResult.Error(Exception("Error loading data"))
            }
        } catch (e: Exception) {
            Log.e("TAG", e.toString())
            return LoadResult.Error(e)
        }
    }
}

@HiltViewModel
class ProductViewModel @Inject constructor(
    getProductUseCase: GetProductUseCase,
) : BaseViewModel() {

    private val _productList: StateFlow<PagingData<Product>> =
        getProductUseCase.invoke()
            .cachedIn(viewModelScope)
            .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), PagingData.empty())
    val productList get() = _productList

but there is a problem that requires searching through multiple parameters. I currently have to use three parameters. (Query String, Category, Product Division)

Whether the search term changes or the category changes, the data must change with each change.

As a result of searching, it was found that using switchMap runs the lambda function whenever LiveData changes.

But since I'm using Flow, I saw a document that flatMapLatest is doing exactly the same thing in Flow, so I wrote the code as follows:

private val _division: MutableStateFlow<String> = MutableStateFlow("All")
private val _query: MutableStateFlow<String?> = MutableStateFlow(null)
private val _category: MutableStateFlow<Int?> = MutableStateFlow(null)

@OptIn(ExperimentalCoroutinesApi::class)
private val _productList: StateFlow<PagingData<Product>> =
    _query.flatMapLatest { queryString ->
        _category.flatMapLatest { categoryId ->
            _division.flatMapLatest {
                val productDivision = if (it == "All") null else it

                getProductUseCase.invoke(queryString, categoryId, productDivision)
                    .cachedIn(viewModelScope)
            }
        }
    }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), PagingData.empty())

However, it only works when initialized (when all parameters are in the initial situation) and does not work whenever the parameters change.

What should I do in this situation?

0

There are 0 answers