Alexander Karkossa
02/18/2021, 3:50 PMval state: StateFlow<HomeViewState>
get() = _state
init {
viewModelScope.launch {
combine(
...
}.collect {
_state.value = it
}
}
}
Why don't use return value of the combine method directly to the state variable?
val state = combine(
...
)
Can someone explain the benefits of viewModelScope.launch -> collect in the init?Alexander Sitnikov
02/18/2021, 4:39 PMcombine()
returns just a Flow
, whereas state's type is StateFlow
. The important difference between the two is that StateFlow
has a value
property, that you can always read from a non-suspending function.
Having _state
property in the view model allows you to write to it from any method of this view model. But if you know for sure, that state
will only ever be computed from this single combine
, you can use stateIn()
operator, which turns any Flow
into StateFlow
:
state = combine(...)
.stateIn(viewModelScope, SharingStarted.Eagerly, initialValue = false)
Alexander Karkossa
02/18/2021, 4:50 PMStateFlow
over Flow
, when the state
is only used in compose with collectAsState
and never used elsewhere?Alexander Sitnikov
02/18/2021, 5:04 PMStateFlow
designed specifically to be used in UI situations. Flow.collectAsState
requires you to provide initial value, and StateFlow.collectAsState
reads value from state
field - that way view knows less about business logic, which is good. Also, StateFlow
collection never throws, but Flow
collection canLaunchedEffect
(which collectAsState
uses under the hood), but I imagine nothing particularly goodcb
02/18/2021, 6:42 PMStateFlow
is useful here, as you don’t need to provide a default value when using collectAsState()
, as @Alexander Sitnikov explained.Alexander Karkossa
02/18/2021, 6:56 PMcollect
the Flow
within a couroutine
to set the value into a StateFlow
? In the jetcaster example, the stateIn
(as @Alexander Sitnikov explained) would also work, until you don't change the value from anywhere else right?cb
02/19/2021, 7:33 AM