Why if I get a flow inside a corutine, it doesn't ...
# compose
p
Why if I get a flow inside a corutine, it doesn't collect, but if I do without corutine but with using
.launchIn(viewModelScope)
it does? Doesn't collect:
Copy code
init {
    viewModelScope.launch {
        busDataRepository.getBusStops()
            .map<List<BusStop>, BusStopsDBScreenUiState> { busStops ->
                BusStopsDBScreenUiState.Success(busStops, Res.string.bus_stops_db_filled)
            }
            .onEach { newState -> _uiState.emit(newState)}
            .catch { throwable -> _uiState.emit(BusStopsDBScreenUiState.Error(throwable))}
    }
}
Do collect:
Copy code
init {
    busDataRepository.getBusStops()
        .map<List<BusStop>, BusStopsDBScreenUiState> { busStops ->
            BusStopsDBScreenUiState.Success(busStops, Res.string.bus_stops_db_filled)
        }
        .onEach { newState -> _uiState.emit(newState)}
        .catch { throwable -> _uiState.emit(BusStopsDBScreenUiState.Error(throwable))}
        .launchIn(viewModelScope)
}
f
1. not compose question 2. you don't collect anywhere in the first example.
onEach
is not terminal operator. You have to call
.collect { }
👍 2
c
There is #C1CFAFJSK for questions like this.
m
To further clarify, functions like map, onEach, and catch are just transformation operators that transform and operate on the data in the flow. Flows in kotlin are generally "cold" flows, in that they do not actually do anything until they are subscribed to with a terminal operator such as "collect" or "launchIn". The general rule is if an operator on a flow has the "suspend" keyword that means the flow will start producing data. If it does not, it's just a transformational operator that does not initiate collection.
p
But why the first code does not collect and the second one does?
a
👍 1
m
yeah, lauchIn is one of those odd operators that is designed for shortening your code so that you can easily collect a flow inside of a give scope (usually viewModelScope) and use the onEach callbacks to process the data instead of a lambda on the collect function.
p
it's a good and common practice to call collect on a viewmodel?
does that mean that will collect continuosly? receiving more data if more data is stored on Room? busDataRepository.getBusStops() returns data from Room.
m
Yes, it will continuously collect so long as the lifecycle of that view model's store is resumed. As to whether it's good practice depends on your use case. In most cases, you would want the view model to update based on the contents of a flow so that your UI updates.