Checking the Jetnews sample app there's this code ...
# compose
j
Checking the Jetnews sample app there's this code snippet that allows state collection from a composable:
Copy code
private val viewModelState = MutableStateFlow(HomeViewModelState(isLoading = true))

val uiState = viewModelState
    .map { it.toUiState() }
    .stateIn(
        viewModelScope,
        SharingStarted.Eagerly,
        viewModelState.value.toUiState()
    )
My question is, what's the advantage of using
stateIn()
here? I would normally do something like:
Copy code
private val _viewModelState = MutableStateFlow(HomeViewModelState(isLoading = true))
val viewModelState get() = _viewModelState
But looking into the
stateIn()
docs there's a mention to increased performance for multiple observers since the upstream flow is instantiataed only once, but what if the flow is collected from a single composable? is there really an advantage there? I was thinking that each recomposition can be considered as a new observer, in which case I can see how the use of
stateIn()
helps, but I'd like to fully understand the implications of its usage and how it's better, so if anyone can shed some light I'd be grateful.
If anyone thinks this is more of a #coroutines question let me know.
a
kind of an #android or #android-architecture question, really. 🙂 either way though, it's trying to satisfy conflicting requirements: the source of truth isn't a
UiState
, it's something that gets mapped to one, and if you don't have a
StateFlow
then you don't have an initial value available, you have to subscribe and wait for it to emit, and in the case of consuming from compose that means you get a frame of empty data before the first item is known.
the whole thing could instead be written as:
Copy code
private var viewModelState by mutableStateOf(HomeViewModelState(isLoading = true))
val uiState: UiState
  get() = viewModelState.toUiState()
to leverage snapshots instead and skip all of the subscription complexity, since the upstream source of truth is a
MutableStateFlow
anyway - a hot data source that doesn't care about subscription awareness in the first place.
j
Thanks! Would you then recommend mutating the state within the ViewModel and exposing it directly instead of using
collectAsState()
?
Also, out of curiosity, do you think the statement "...each recomposition can be considered as a new observer" is true?
a
the call to
.collectAsState
is an observer for as long as it remains in composition with the same receiver flow instance
the same underlying observer (call to
Flow.collect
persists undisturbed across recompositions for as long as the call to
.collectAsState
is present in the composition for the same
Flow
instance
j
I see now, thanks again, appreciate your help