K Merle
10/07/2021, 7:49 AMJoffrey
10/07/2021, 8:13 AMViewModel
lives, you probably should use viewModelScope
. If they should outlive the ViewModel
, then it would be appropriate to use a custom scope for that.
The main "danger" in my opinion is that you have to manually control the lifetime of that scope (in other words, don't forget to cancel()
it when appropriate)K Merle
10/07/2021, 8:17 AMJoffrey
10/07/2021, 8:18 AMCoroutineScope()
factory function, you have to cancel it manually in any case (the goal is to prevent coroutines from leaking if one doesn't end properly).K Merle
10/07/2021, 8:18 AMJoffrey
10/07/2021, 8:19 AMStateFlow
, you most likely should use viewModelScope
instead of a custom one, because you're not interested in that state outside of the viewmodel right?K Merle
10/07/2021, 8:20 AMJoffrey
10/07/2021, 8:22 AMDisptacher
, not the scope per se. The scope provides a default dispatcher, but all coroutine builders accept a parameter to launch coroutines on a different dispatcher (e.g. scope.launch(<http://Dispatchers.IO|Dispatchers.IO>)
).
In the case of a flow, you could use myFlow.flowOn(<http://Dispatchers.IO|Dispatchers.IO>).stateIn(viewMoedlScope)
(of course you can replace <http://Dispatchers.IO|Dispatchers.IO>
by whichever dispatcher you want to use here)K Merle
10/07/2021, 8:25 AMK Merle
10/07/2021, 8:27 AMviewModelScope
will inherit previously declared scope inside flowOn
Joffrey
10/07/2021, 8:29 AMflowOn
only affects preceding steps in the flow, the context is always preserved on the collector side.
In short, everything before .flowOn
in the flow definition will run on IO dispatcher, and everything between flowOn
and stateIn
will run on whichever default dispatcher is provided by viewModelScope
(most likely Main as you said). There is nothing between flowOn
and stateIn
in the provided snippet, so nothing from this flow will actually run on Main here.
However, the collectors of the resulting flow will run their collect
on whatever dispatcher they are using.K Merle
10/07/2021, 8:30 AMNick Allen
10/07/2021, 3:41 PMmyFlow.stateIn(viewModelScope + <http://Dispatchers.IO|Dispatchers.IO>)
You can use +
to create a new scope with the same lifetime but a different dispatcher (or any context element, only Job
controls lifetime).
This will run the flow and collect on the IO
dispatcher so there is no dispatch just to update the StateFlow.Joffrey
10/07/2021, 3:49 PM+
here 🙂
This will run the flow and collect on theNo, not the collectors. All flows must preserve the collector's context, and this is also true if you usedispatcherIO
stateIn(viewModelScope + <http://Dispatchers.IO|Dispatchers.IO>)
. The collectors will execute in whichever context there are called from, not on the dispatcher specified here.Nick Allen
10/07/2021, 7:33 PMstateIn
starts a new coroutine. It collects using the specified scope.Joffrey
10/07/2021, 7:35 PM