Observe on the correct thread

Dionysis Lorentzos
Dionysis’ desk
Published in
3 min readSep 6, 2015

--

Although people understand the logic of RxJava there is still a lot of confusion in which thread you should run the observable’s chain and its operators.

First of all let’s clear out what’s the difference between .subsribeOn() and .observeOn() in RxJava:

  • The .subscribeOn() changes the Scheduler where the Observable should operate.
  • The .observeOn() changes the Scheduler where the Observable will send notifications.
  • Additionally you need to know that by default, the chain of operators will work on the same thread on which its .subscribe() method is called.

Let’s see some examples:

1. Main thread / .subscribe() thread

If you have this method in Android Activity’s onCreate() which runs in the main thread, then the following code:

Observable.just(1,2,3)
.subscribe();

will behave like that:

2. .subscribeOn()

Even if you have the snippet run in the main thread, then the whole code block will run on the .subsribeOn() defined thread:

Observable.just(1,2,3)
.subscribeOn(Schedulers.newThread())
.subscribe();

3. .observeOn()

If you have the snippet run in the main thread, by default the Observable will be created on the .subscribe() thread but after the .observeOn() is being called then the rest of the code block will run on the defined thread:

Observable.just(1,2,3)
.observeOn(Schedulers.newThread())
.subscribe();

3. Combined logic

Of course the operators are meant to be combined. Together they look like that:

Observable.just(1,2,3)
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe();

Tips / Gotchas:

1. “run in the ui thread exception”

Observable.just(1,2,3)
.subscribeOn(Schedulers.newThread())
.subscribe(/** logic which touches ui **//);

obviously.

2. Keep the logic in the background

Instead of doing this:

Observable.just(1,2,3)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.flatMap(/** logic which doesn't touch ui **//)
.subscribe();

do this:

Observable.just(1,2,3)
.subscribeOn(Schedulers.newThread())
.flatMap(/** logic which doesn't touch ui **//)
.observeOn(AndroidSchedulers.mainThread())
.subscribe();

By using the second snippet over the first one the flatMap (or any other logic on that point) will run on the background. This will not block the UI thread in Android, cause ANRs or similar issues. It’s similar to putting as much logic possible to the AsyncTask’s .doInBackground() instead of the .onPostExecute().

3. Earlier .subscribeOn() wins

Having the following:

Observable.just(1,2,3)
.subscribeOn(thread1)
.subscribeOn(thread2)
.subscribe();

Both observable creation and .subscribe() will run on thread1 as the logic will overwrite the thread2. So there is no need to have more that once the .subscribeOn() operator.

Thank you for reading!

Want to learn more about me? I’m Dionysis, an Android dev at ShareNow + Founder of Nutech, a jobs app only for Android developers.

If you are an Android developer, you will most likely be interested in Nutech app.

--

--

Dionysis Lorentzos
Dionysis’ desk

Dionysis is an Android dev ShareNow + Founder of Nutech, a jobs app only for Android developers. He is passionate about auto industry innovation & space