No More Disposable Observer as Callbacks Please

Stephen Jan
ClassPass Engineering
3 min readFeb 28, 2019

--

This blog post was inspired by an article that DoorDash Engineering posted describing the transition from Callbacks-Style API calls to Rx-Style API calls. In this article, I highlight some of their points as they relate to some of ClassPass’s legacy Android code base.

The ClassPass code base currently follows a pattern where the Presenter component creates and passes a DisposableObserver to the Interactor layer, which in turn passes the callback to the repository layer. (Presenter from MVP Architecture).

DisposableObserver Example:

Example of Common RxJava Usage in ClassPass Codebase

Let’s not do this any more.

  • Callback Hell — The pattern above uses DisposableObserver as a callback and reinforces the Callback Hell problem.
  • Readability — Keeping relevant logic together makes code more readable. The pattern above spreads relevant logic over different layers and components.
  • Testing — Unit testing the Presenter requires instantiating multiple layers to simulate the test logic. This is not ideal for unit tests.

Example:

Example of test that instantiates and mocks 3 layers: Presenter, Interactor, Repository
  • Rx offers better — RxJava/RxKotlin has grown in popularity in direct response to challenges around organizing asynchronous logic. Operators such as flatMap serve as an alternative to callbacks.

The Better: Observable Chaining

Rather than using the DisposableObserver as a callback, we should return the result as an Observable.

Before:

interactor.fetchData(input: Data, callback: DisposableObserver<>)

After:

interactor.fetchData(input: Data) : Observable<>

Refactoring the Interactor

Using the proposal pattern we refactor ReviewInteractorImpl.

ReviewInteractorImpl Before:

ReviewInteractorImpl After:

interactor no longer manages the subscribe/unsubscribe

Refactor the Presenter

The Presenter layer refactor will reintroduce 2 components removed from the Interactor layer.

  • subscribeOn and observeOn — the logic the ensures IO doesn’t happen on main thread.
  • subscribeWith — The binding between callback logic and API response

Also, we refactor the Inner class ClassReviewListObserver into the Observable chain.

ReviewPresenterImpl Before:

ReviewPresenterImpl After:

Refactor Tests

Finally, removing the callback no longer requires the unit test to instantiate the Repository.

In summary, replacing DisposableObserver with Observable Chains gets us a couple things.

  1. Readability — ReviewPresenterImpl chains together all the logic describing the behavior of fetchVenueReviewList.
  2. Cleaner Tests — The unit test does not reference the Repository anywhere and only mocks the Interactor.
  3. No Callbacks — No Callback Hell 🎉
  4. Rx Operators like flatMap and doOnError

The example illustrates how we can refactor logic in the Presenter layer and how ReactiveX deals with async behavior without callbacks. With only one call to the api layer,fetchVenueReviewList is pretty straightforward. For more complex scenarios like chaining api calls, ReactiveX offers many more operators.

Let’s leverage ReactiveX’s true potential and kick DisposableObserver aside. 🎊

You’re reading the ClassPass Engineering Blog, a publication written by the engineers at ClassPass where we’re sharing how we work and our discoveries along the way. You can also find us on Twitter at @ClassPassEng.

If you like what you’re reading, you can learn more on our careers website.

--

--