These are chat archives for ReactiveX/RxJava
RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.
subscribeOnas firebase handles calling stuff in the background itself. However if you need to process data returned from firebase elsewhere (on another thread), you need to schedule it yourself. Use
observeOndoes not solve your problem?
.observeOn()does give me the ability to process the data returned by Firebase on another thread. That's what I'm doing already, but it just isn't the point of the question. The point is: when I pass a Scheduler through
.subscribeOn()I expect the upstream to conform to that Scheduler's thread but that doesn't happen when the Observable has an internal listener that is being triggered from a callback on a different thread. When that happens, I lose the
.observeOn()after any call to that method? Should the library call an
.observeOn()itself and call it a "default Scheduler"? In any of these cases the
.subscribeOn()is just useless, and that doesn't seem right to me.
subscribeOn, somehow (and especially on RxJava) is a overused operator that rarely does what's expected. And indeed, as you have experienced, it doesn't do what you expected.
subscribeOnwill register the events on the thread specified in
subscribeOn, but that does not mean the callback from those events will happen on the same thread that was used ot register them. A proper library might indeed do so, but more often libraries wil use their own internal threads, or in case of Firebase, use the main thread apparently. This is a problem with Firebase, not Rx. If you implement something like this in Rx, it would be smart to use the trampoline sceduler (i.e. same thread scheduler) to prevent these problems.
observeOnis merely a hotfix that will ensure the main thread isnt tied up long while you process an event.
Oh and to come back to your question
Should the library enforce its clients to always call an .observeOn() after any call to that method?
No, instead it would be best practice for clients to not do any long computations on the event dispatcher. If you dont do anything long running, it's way more efficient to simply borrow the already active thread, as context switching is expensive on itself. If you do need to do long running computations, it's always a smart idea to schedule these in the background, preferably in parallelle.
source.flatMap(e => longRunning(e), computationScheduler)
subscribeOnis provided as the means to move the subscription side effects to another thread. Many sources, such as most listener APIs don't have subscription side effects and
subscribeOnis completely ineffective. When these sources emit, that can happen from any thread. UI-like sources emit from the main thread, dedicated sources emit from their own background thread. In order to process these the required place, you should use
observeOn. In addition, you may want to run your own single-threaded scheduler via
Schedulers.from(Executors.newSingleThreadedExecutor())which guarantees observing on it from multiple stages will end up on the same thread in a serialized manner.
.subscribeOn()! Thanks for that. I'm just not so sure if I understood your suggested solution with
.observeOn()and also what you meant by "guarantees observing from multiple stages".
observeOn()multiple times in a sequence because you route computation back and forth.
Schedulers.computation()will hand out a Scheduler that provides separate thread (from a fixed set) to each use of
observeOnand it is very unlikely two
observeOnwill run on the same thread.