https://kotlinlang.org logo
Title
a

alexsullivan114

11/02/2019, 8:33 PM
Flow/Coroutines question: I'm trying to migrate from RxJava to Flow for Android apps. I often write apps where in some starting point of the app (onCreate or the ViewModel init function for example) I subscribe to a bunch of observables. So, a typical
init
of a view model of mine may look like this:
init {
    myObservable
        .filter { whatever() }
        .map { whatever() }
        .subscribe { pushToMySubject() }

    myOtherObservable
        .filter { whatever() }
        .map { whatever() }
        .subscribe { pushToMyOtherSubject() }

    myThirdObservable
        .filter { whatever() }
        .map { whatever() }
        .subscribe { pushToMyThirdSubject() }
}
But when using flow, we can only call
collect
(which if I'm not mistaken is analagous to
subscribe
in RxJava) from within a coroutine context, which makes sense. But, as far as I can tell, calling
collect
blocks that coroutine context (my terminology might be garbage here) so you can't really have the above setup because we wouldn't execute the last two subscribes until the first observable completes. So two questions: 1. Is my understanding correct? 2. What's the preferred path to handle this sort of scenario?
o

octylFractal

11/02/2019, 8:38 PM
are these intended to live beyond
init
?
a

alexsullivan114

11/02/2019, 8:38 PM
yes
Again this is getting into Android specifics, but there's a coroutine context scoped to the viewmodels lifecycle that the Android APIs expose
o

octylFractal

11/02/2019, 8:39 PM
I think the correct method here is
viewModelScope.launch
a

alexsullivan114

11/02/2019, 8:39 PM
yeah that's what I'm using
o

octylFractal

11/02/2019, 8:39 PM
you would
launch
for each thing you want to collect
a

alexsullivan114

11/02/2019, 8:39 PM
Got it - so for the above flow, we'd want three different calls to
launch
o

octylFractal

11/02/2019, 8:39 PM
yea
a

alexsullivan114

11/02/2019, 8:39 PM
word. Thank you!
d

Dominaezzz

11/02/2019, 8:49 PM
You can also call
.launchIn(viewModelScope)
on the flow itself.
☝️ 2
a

alexsullivan114

11/02/2019, 10:24 PM
Awesome tip, thanks Dominic!
a

alexsullivan114

11/03/2019, 2:41 PM
So if you use
launchIn
you really need to use
onEach
or some other side effect operator to actually process your items. Interesting.
e

elizarov

11/03/2019, 2:43 PM
Yes. It is just a DSL. Instead of
compositeDisposable.add(..... .subscribe { ... })
you do
.... .onEach { ... }.launchIn(scope)
You use
scope
instead of
compositeDisposable
to track subscriptions and make sure they are closed.