How to handle many Api requests using Paging 3

Following this codelab I have implemented pagination and caching using RemoteMediator (I am calling a simple API that returns a list of news). I am injecting this RemoteMediator to Repository which has method getResultStream() that returns Flow<PagingData<News>>. In ViewModel is function getNews() : Flow<PagingData<News>> and in Fragment I am calling this function and submitting list to RecyclerAdapter.

Now I want to add a new API call that returns news but with search keyword. What is the proper way to do it? Do I have to write all this code again and create a new RemoteMediator? The logic will be the same but now I have to pass a string argument to the Retrofit get function. The result of this call will replace items in RecyclerView, so I will have two sources of data but one Recycler, do I have to create also a MediatorLiveData? (I don’t add any code but if it help I can do it)

One person asked how exactly I did it (Question posted as answer so it is deleted now but maybe it will help someone in future). So, in ViewModel I have this:

// this flow keeps query. If it is null it means that I want to get all News from API. If it is not null it means that I want to make another API request which takes a parameter query
private val _queryFlow: MutableStateFlow<String?> = MutableStateFlow(null)
val queryFlow: StateFlow<String?>
    get() = _queryFlow

// this function set and validate query
fun submitQuery(query: String?)
    Timber.d("Submit new search $query")
    _queryFlow.value = when
        query.isNullOrEmpty() -> null
            .isNotBlank() -> query.trim()
        else -> null

// flow of paging data that I am using in RecyclerView
val homeNewsData = _queryFlow.flatMapLatest {

private fun searchNews(
    query: String?
): Flow<PagingData<NewsRecyclerModel>>
    return newsRepository.getSearchResultStream(
        // mapping, filtering, separators etc.

NewsRepository has this function used in VM:

fun getSearchResultStream(searchKey: String?): Flow<PagingData<News>>
    val pagingSourceFactory = { database.cacheNewsDao.getNews() }
    return Pager(
        config = PagingConfig(
            pageSize = NETWORK_PAGE_SIZE,
            enablePlaceholders = false,
            initialLoadSize = INITIAL_LOAD_SIZE
        remoteMediator = newsRemoteMediator.apply { this.searchKey = searchKey },
        pagingSourceFactory = pagingSourceFactory


// it keeps submitted query. based on this I can letter define which API request I want to do
var searchKey: String? = null

override suspend fun load(loadType: LoadType, state: PagingState<Int, News>): MediatorResult
    \ all logic the same like in codelabs

        val apiResponse =
            if (searchKey.isNullOrEmpty()) // query is null/empty get Trending news
                    page * state.config.pageSize
            else // query is not blank, make API request with search keyword
                    page * state.config.pageSize,
        \ again the same logic like in codelabs
I don’t know if it is the best way to do it (probably not) but in my case, it was working


Assuming you still have one recyclerview, you can do something like:

val queryFlow = MutableStateFlow(startingQuery)
queryFlow.flatMapLatest { query ->
    Pager(..., MyRemoteMediator(query)) {