Skip to content

Instantly share code, notes, and snippets.

@AdnanHabibMirza
Last active July 31, 2024 23:58
Show Gist options
  • Save AdnanHabibMirza/3fdb7d4a3728222f6968cd75f94a3200 to your computer and use it in GitHub Desktop.
Save AdnanHabibMirza/3fdb7d4a3728222f6968cd75f94a3200 to your computer and use it in GitHub Desktop.
Instant Search using Kotlin Coroutines/Flows with Single Source of Truth (SSOT)
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
class SearchViewModel : ViewModel() {
private val _searchQuery = MutableStateFlow("")
val searchQuery: StateFlow<String> = _searchQuery
val searchResults: StateFlow<List<String>> = _searchQuery
.debounce(300L)
.distinctUntilChanged()
.flatMapLatest { query ->
if (query.isBlank()) {
flowOf(emptyList())
} else {
fetchSearchResults(query)
.catch { emit(emptyList()) }
}
}
.flowOn(Dispatchers.IO)
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000L),
initialValue = emptyList()
)
fun onSearchQueryChange(query: String) {
_searchQuery.update { query }
}
private fun fetchSearchResults(query: String) = flow {
delay(3_000L)
emit(
listOf(
"Result 1 for $query",
"Result 2 for $query",
"Result 3 for $query",
"Result 4 for $query",
"Result 5 for $query"
)
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment