updateStateWith

context(viewModel: ViewModel)
inline fun <T : Any> MutableStateFlow<UiState<T>>.updateStateWith(crossinline operation: suspend T.() -> Result<T>)

Updates the UI state with the result of an async operation that returns new data.

This function automatically handles the complete async operation lifecycle:

  1. Sets loading = true before starting the operation

  2. Executes the operation in the ViewModel's coroutine scope

  3. Updates state with new data on success

  4. Sets error event on failure

  5. Sets loading = false when complete

Use this function for async operations that fetch or compute new data, such as:

  • Loading data from a repository

  • Refreshing screen content

  • Search operations

  • Any operation that returns Result<T> with new data

Kotlin Context Parameters

This function uses Kotlin's context parameters feature (context(viewModel: ViewModel)). The ViewModel context provides implicit access to viewModelScope for launching coroutines. You never need to pass the ViewModel explicitly - it's automatically available when called from within a ViewModel.

Usage Example

@HiltViewModel
class HomeViewModel @Inject constructor(
private val repository: HomeRepository
) : ViewModel() {
private val _uiState = MutableStateFlow(UiState(HomeScreenData()))
val uiState = _uiState.asStateFlow()

fun loadData() {
_uiState.updateStateWith {
repository.getData() // Returns Result<HomeScreenData>
}
}

fun search(query: String) {
_uiState.updateStateWith {
repository.search(query) // Returns Result<HomeScreenData>
}
}
}

Error Handling

  • Errors are automatically caught and wrapped in OneTimeEvent

  • The error is displayed via StatefulComposable's snackbar mechanism

  • Original data is preserved when an error occurs

Duplicate Requests

If called while loading = true, the function returns immediately to prevent duplicate concurrent operations.

Parameters

T

The type of the screen data.

operation

Suspend lambda that receives current data and returns Result<T> with new data. Typically calls a repository method that returns new screen data.

See also

for synchronous updates

for async operations that don't return new data

suspendRunCatching

for wrapping repository operations in Result

Samples

dev.atick.feature.home.ui.item.ItemViewModel.createOrUpdateJetpack