1

I want to debounce the items sent to a shared flow, and consume them after that. Something like this:

private var flow = MutableSharedFlow()

suspend fun search(query: String): Flow<Result> {
   flow.emit(query)
   return flow.debounce(1000).map{ executeSearch(it) }
}

The event that initiates the search is a user writing on a field. For each character, the search function is called. So I want to get a debounced result, to avoid many queries to the server. It looks like the debounce operator returns a different flow instance each time, so that all the queries end up invoking the executeSearch() function, without dropping any of them as you could expect by using a debounce operator. How can I achieve a functionality like this, so that a client can invoke a function that returns a flow with debounced results?

General Grievance
  • 4,555
  • 31
  • 31
  • 45
user1116714
  • 315
  • 2
  • 3
  • 12

2 Answers2

1

With two flows you could do it like this. One backing flow takes all the search inputs, and the second is a debounce version of it that runs the query. The search function doesn’t return a flow because the Flow is already available as a property and we aren’t creating new ones for each input.

private val searchInput = MutableSharedFlow<String>()

val searchResults = searchInput.debounce(1000)
    .map { executeSearch(it) }
    .shareIn(viewModelScope, SharingStarted.Eagerly)

fun submitSearchInput(query: String) {
   searchInput.tryEmit(query)
}

You could alternatively do it with jobs that you extinguish when new inputs come in:

private val searchJob: Job? = null

private val _searchResults = MutableSharedFlow<SearchResultType>()
val searchResults = _searchResults.asSharedFlow()

fun submitSearchInput(query: String) {
    searchJob?.cancel()
    searchJob = viewModelScope.launch {
        delay(1000)
        _searchResults.emit(executeSearch(query)) 
    }
}
Tenfour04
  • 83,111
  • 11
  • 94
  • 154
0

You can try something like this:

private var flow = MutableSharedFlow()

init {
    flow.debounce(1000)
        .collect { 
            val result = executeSearch(it)
            // Process the result (maybe send to the UI) 
        }
}

suspend fun search(query: String) {
   flow.emit(query)
}
Arpit Shukla
  • 9,612
  • 1
  • 14
  • 40