Chapter 9: Observable’s action operators

android2ee (Seguy Mathias)
4 min readJan 5, 2021

We will see the following actions on Observables: To manage emitted events (we’ll see that’s not absolutely true) :

  • doOnNext
  • doOnEach

To manage the life cycle of the observer :

  • doOnLifecycle
  • doOnRequest
  • doOnSubscribe
  • doOnUnsubscribe
  • doOnError
  • doOnComplete
  • doOnCompleted
  • doOnDispose
  • doOnTerminate
  • doAfterTerminate
  • doFinally

And those related to errors recovery :

  • onErrorReturn
  • OnErrorReturnItem
  • onErrorResumeNext
  • retry

For this chapter, we keep using the days of the week observable.

But we will also use the interval observer :

doOnEach versus doOnNext

Stream is not changed They will both do an action when the next item is called.
doOnNext receives only the emitted items
doOnEach receives all the events : onNext,OnError and onComplete
So if you are only interested by the emitted items, use doOnNext.
If you are interested by the whole lifecycle (next/error/complete), use doOnEach

doOnEach

Stream is not changed The behavior of doOnEach is clearly understandable using this code:

doOnNext

The behavior of doOnNext is clearly understandable using this code:
Stream is not changed

Tracking the lifeCycle of the observable

We can schedule an action according to any event of the life cycle of the observable using one of those action operators:

  • doOnLifecycle
  • doOnSubscribe
  • doOnComplete
  • doOnCompleted
  • doOnDispose
  • doOnTerminate
  • doAfterTerminate
  • doFinally

The only important point is the difference between an observable that reaches the onComplete and those which are disposed before onComplete happens.
If the observable reaches the onComplete then you’ll receive the :

  • OnComplete
  • OnTerminate
  • OnAfterTerminate
    If the observable is disposed before the onComplete is reached, you’ll receive the :
  • onDispose
    But you can not receives both events set, either it’s the onComplete reached case, either it’s the onDispose case.

To see that we will test both cases and see what happens:

Reaching the onComplete

Let’s test what happen with an observable that reaches the onComplete :

Reaching the onDispose

Let’s test what happen with an observable that reaches the onDispose :

Error actions:

There are several types of actions you can do on error, to track them or recover, let’s see that.
So the first remark is that exception will break your observer chain and kill it by firing the exception.
OnDispose is not called, onComplete neither, you just fall in the onError block of the Observer (the closest to the error) and receieves the onTerminate.
But sometimes we want to intercept the error in the chain and changes the behavior from here.
To dick into this error “management”, we will use this observable:

Normal behavior when error happened

We will use the lifecycle operators to understand the behavior when an error is send.
When the exception is thrown, it will break the RxChain and the following calls are done:

  • onTerminate
  • OnError
  • The exception is thrown
  • onFinnaly
  • And onAfterTerminate And your chain is over.

Dying cleanly

You cannot recover from an exception thrown. The only thing you can do is to have a last action before dying.
So you can:

  • retry the observation by restarting your chain
  • emit an item and complete
  • emit several items and complete
  • run another observable and complete

The important fact to have in mind is that your chain is over. What ever you will do, in the best case, onComplete will be called and you can sent last items before dying. This is the only action you can do. You can not resume or keep going with the chain In a way there is no possible recovery, you can only die nicely.

Dying nicely with onError**

You can use one of those 3 operators:

  • onErrorReturn
  • OnErrorReturnItem
  • onErrorResumeNext

They will all act the same: Do the last action and complete the chain. You will avoid to fall in the onError bloc of the observer. :

Using onErrorResumeNext

Using onErrorReturnItem

Using onErrorReturn

Retry

You can also just rerun your Observable source and see if the exception happens again.
You have to be aware that if you use this pattern and the exception raises again, you will just die, onComplete will not be called and you will fall in the onError bloc of the final observer.

A nice usual way to use onErrorResumeNext

A nice usual way to handle the exception is to emit and empty “item” and just onComplete nicely. This is more for your Rx-culture.
(but we can wonder why you want to avoid to run in your onError bloc)

More on the topic

Previous chapter: Chapter 8: Observable’s collection transformers operators

Next chapter:

This chapter is a small part of a biggest training project, you can find on Github. You’ll have the main branch with the answers/responses/unit tests and documentation. You could start with the “questions” branch to only have the questions.

You’ll have the full table of content of the articles on Medium.

You can download the book on Android2ee

Warning: Those articles has been created only because I am stuck in a Rx Android project and I need to prepare the ramp up for those who will replace me.

My conclusion : Choose Kotlin and suspending function instead of Rx. PLEASE, save your project from RxHell !!!

Write Medium in Markdown? Try Markdium!

--

--

android2ee (Seguy Mathias)

Android2ee alias Mathias Seguy. Android expert gives you some news on the Android world. mathias.seguy@android2ee.com