StateFlow
A hot flow that holds a single value and emits updates to collectors. Always has an initial value.
Basic Usage
Section titled “Basic Usage”class MyViewModel : ViewModel() { private val _uiState = MutableStateFlow("Initial") val uiState: StateFlow<String> = _uiState.asStateFlow()
fun updateState(newValue: String) { _uiState.value = newValue }}Collect StateFlow in Composable
Section titled “Collect StateFlow in Composable”@Composablefun MyScreen(viewModel: MyViewModel = viewModel()) { val uiState by viewModel.uiState.collectAsState()
Text(text = uiState)}StateFlow vs LiveData
Section titled “StateFlow vs LiveData”| StateFlow | LiveData |
|---|---|
| Requires initial value | Can be null initially |
| Kotlin coroutines based | Lifecycle-aware by default |
collectAsState() in Compose | observeAsState() in Compose |
StateFlow vs SharedFlow
Section titled “StateFlow vs SharedFlow”| StateFlow | SharedFlow |
|---|---|
| Always has current value | No initial value required |
.value to read current | No .value property |
| Conflates (skips intermediate) | Configurable buffer/replay |
| Best for UI state | Best for events/actions |
Using by keyword
Section titled “Using by keyword”To use the by keyword in compose, import:
import androidx.compose.runtime.getValueimport androidx.compose.runtime.setValueManual Recompose
Section titled “Manual Recompose”var count by remember { mutableStateOf(0) }key(count){ // recompose when the var count change}snapshotFlow
Section titled “snapshotFlow”Kind of like LaunchedEffect but allows use in non-composable functions
snapshotFlow { searchQuery } .filter { it.length > 2 } // Only emit if query is longer than 2 characters .debounce(500) // Wait 500ms after last change .collect { query -> println("Search query: $query") // Example: Trigger a network search }