Flow represents a stream of values emitted over time — think of it as the coroutine-native equivalent of an observable sequence:
fun observeSearchResults(query: Flow<String>): Flow<List<Result>> {
return query
.debounce(300) // wait for typing to pause
.filter { it.length >= 2 } // ignore very short queries
.distinctUntilChanged() // skip if unchanged
.flatMapLatest { text ->
flow { emit(searchApi.search(text)) }
}
}
StateFlow is a hot, state-holding Flow — the modern replacement for LiveData in new codebases, with the key difference that it always has a current value and works naturally with Compose:
class SearchViewModel : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Idle)
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
fun search(query: String) {
viewModelScope.launch {
_uiState.value = UiState.Loading
_uiState.value = UiState.Success(repository.search(query))
}
}
}
SharedFlow is for one-off events (like showing a Snackbar) that shouldn’t replay to every new observer the way StateFlow’s current value does — use it for events, StateFlow for state.
- Image
- SKU
- Rating
- Price
- Stock
- Availability
- Add to cart
- Description
- Content
- Weight
- Dimensions
- Additional information