Hristijan
09/18/2024, 6:23 PMval myScreenState = flow<ScreenState> {
val newsAsync = async { newsRepository.getNews() }
val headlinesAsync = async { newsRepository.getHeadlines() }
emit(ScreenState(news = newsAsync.await(), headlines = headlinesAsync.await()))
}.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(CommonConstants.COLLECT_TIMEOUT),
ScreenState()
)
I want to achieve parallelism, but async can’t be used since it needs a scope and inside a ViewModel I have access to the viewModelScope
but it can’t be used in the flow builderSam
09/18/2024, 6:37 PMSam
09/18/2024, 6:38 PMHristijan
09/18/2024, 7:58 PMcoroutineScope
it returns a result, after it does return everything I emit the value and it’s still possible to emit it while in the coroutineScope
but I guess it’s not a good practice or if i need to emit something to a different flow/state flow?
Where as with the channelFlow
I can just use send to the channel
1. coroutineScope
val myScreenState = flow<ScreenState> {
val screenState = coroutineScope {
val newsAsync = async { newsRepository.getNews() }
val headlinesAsync = async { newsRepository.getHeadlines() }
ScreenState(news = newsAsync.await(), headlines = headlinesAsync.await())
}
emit(screenState)
}.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(CommonConstants.COLLECT_TIMEOUT),
ScreenState()
)
2. channelFlow
val myScreenState = channelFlow<ScreenState> {
val newsAsync = async { newsRepository.getNews() }
val headlinesAsync = async { newsRepository.getHeadlines() }
send(ScreenState(news = newsAsync.await(), headlines = headlinesAsync.await()))
}.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(CommonConstants.COLLECT_TIMEOUT),
ScreenState()
)
i’m trying to understand what’s the difference and which use-case makes sense to use and when 🤔Sam
09/18/2024, 8:02 PMcoroutineScope
is sufficient. The channelFlow
is needed if you want to emit (well, send) values from inside the async
(or launch
) subtask.Hristijan
09/18/2024, 8:12 PMcoroutineScope
managed or I need to manage it’s lifecycle, my question is, after it returns the value, is it still active?Sam
09/18/2024, 8:12 PMHristijan
09/18/2024, 8:14 PMsupervisorScope
or just use coroutineScope
let’s say that the the error handling is handled by the useCase/repositorySam
09/18/2024, 8:17 PMcoroutineScope
function itself will throw an error if one of the child tasks fails. If you swapped it for a supervisor scope, the scope itself wouldn't throw anything, but the subsequent call to await
would throw, so it amounts to much the same thing. I'd stick with coroutineScope
since it will automatically cancel remaining tasks as soon as one fails, making the failure handling more prompt