https://kotlinlang.org logo
#compose
Title
# compose
a

Alexander Karkossa

02/18/2021, 3:50 PM
@cb  I have a question about the ViewModels in the JetCaster app. https://github.com/android/compose-samples/blob/master/Jetcaster/app/src/main/java/com/example/jetcaster/ui/home/HomeViewModel.kt#L46 The state/_state variable (MutableStateFlow) is set by a collect on a combine in a launch on the viewModelScope.
Copy code
val 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?
Copy code
val state = combine(
    ...
  )
Can someone explain the benefits of viewModelScope.launch -> collect in the init?
a

Alexander Sitnikov

02/18/2021, 4:39 PM
combine()
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
:
Copy code
state = combine(...)
    .stateIn(viewModelScope, SharingStarted.Eagerly, initialValue = false)
a

Alexander Karkossa

02/18/2021, 4:50 PM
But what is the benefit of
StateFlow
over
Flow
, when the
state
is only used in compose with
collectAsState
and never used elsewhere?
a

Alexander Sitnikov

02/18/2021, 5:04 PM
Generally speaking,
StateFlow
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 can
2
🤔 1
I don't know what will happen, if exception will be thrown in
LaunchedEffect
(which
collectAsState
uses under the hood), but I imagine nothing particularly good
c

cb

02/18/2021, 6:42 PM
StateFlow
is useful here, as you don’t need to provide a default value when using
collectAsState()
, as @Alexander Sitnikov explained.
a

Alexander Karkossa

02/18/2021, 6:56 PM
OK i unterstand the intention, but it is much more complexity, only for prevent the default value. Is it worth it?
collect
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?
c

cb

02/19/2021, 7:33 AM
stateIn() didn’t exist when I wrote that code iirc, but yeah it should work the same
1
3 Views