Updating your UiState correctly in ViewModel

Cazimir Roman
2 min readNov 26, 2022
Photo by Miguel Á. Padriñán

Assume you have a ViewModel where the init block collects certain flows and the view model’s state flow is modified in accordance with the data being gathered.

private val _uiState = MutableStateFlow(ScreenUiState())
override val uiState: StateFlow<ScreenUiState> = _uiState


init {
collectFlow1()
collectFlow2()
}

private fun collectFlow1() {
viewModelScope.launch {
flow1.collect {
_uiState.value = _uiState.value.copy(
someProperty2 = it
)
}
}
}

private fun collectFlow2() {
viewModelScope.launch {
flow2.collect {
_uiState.value = _uiState.value.copy(
someProperty = it
)
}
}
}

The way you would normally update the state is by by getting the current state value and copying the data class updating the desired properties.

But you should be aware of a racing condition. Another thread may have updated the view state and altered a property that the current copy isn’t changing between the time the copy function completes and the state flow emits its new value.

A problem occurs if one update takes longer than the other and you can get some inconsistent states when getting the current value.

The atomic update extension function can be used as a replacement for the obtain current value copy method. This feature is accessible starting with Kotlin Coroutines version 1.5.1.

_uiState.update {
it.copy(
property1 = newState.property1,
property2 = newState.property2,
...
)
}

Hope this helps.

Before you go…

If you found this article helpful, click the ❤️ or 👏 button below or share the article on Facebook so your friends can benefit from it too.

--

--

Cazimir Roman

A curious developer with a passion for learning and creating innovative solutions to complex problems.