Clean Architecture & RxJava — changing the repository source on the fly

Tom Seifert
May 14, 2018 · 4 min read
Image for post
Image for post

Recently we at grandcentrix had to implement a different polling logic based on a mutating state: in the default state we were fine to read data from the local cache or query the backend if that cache is empty; in another state we needed to hit the backend for updated data in a regular interval.

This mutating state could be everything in your app: location, network or bluetooth settings, time etc.

While heavily using Clean Architecture and RxJava in the app, we wanted to make the state so irrelevant as possible, not interrupting any subscriptions when the state changes, optimally just start to emit regularly to any existing subscribers. But which part of a Clean Architecture application is responsible for checking and observing that state?

Should it be the presenter that checks the state and executes the use case either once or every x seconds? Pretty fast we said no, the presenter should not know anything about the business logic. Also we needed the logic at different places, so it should be the use case to decide, right?

Well, optimally a use case only transforms data it gets from the data layer resp. the repository, applies some logic on the data, like mapping or filtering, and doesn’t decide how or when to get the data.

Further, when reading the note from Fernando Cejas about the data layer, it sounds like an awesome fit:

The idea behind all this is that the data origin is transparent for the client, which does not care if the data is coming from memory, disk or the cloud, the only truth is that the data will arrive and will be got.

So, the repository is already responsible for deciding what data gets returned from where, why not let it decide how often to return it, too? Combined with RxJava this means that our repository does a new network call every thirty seconds, pushes the new data on the upstream and neither the use case, nor the presenter have to care about the state at all, they just transform resp. display the data they receive. Even better, the repository can react on network or connectivity issues by falling back to the local cache, so no other component has to care about errors (although they could)!

The basics

Depending on one of two states we want to make the Observable emit either once or in an interval. Let’s call the two functions that serve the data for either state defaultStateObservable and specialStateObservable and put them in a new class:

Now, let’s make Emitter observe any state changes and call a method when the state changes:

Now we would have to subscribe to the specific Observable depending on the state. The problem is, our repository only has one method to get the data. If a subscriber is already subscribed to defaultStateObservable() and now we need to switch to specialStateObservable(), we cannot tell the subscriber to resubscribe.

Subject to the rescue!

Now we can change the data source on the fly when the state changes while our subscriber doesn’t know anything about it 😎. Each emission of one of the Observables will be delegated to the Subject, so our subscriber receives the event.

Image for post
Image for post
But, wait…

But subscribing to the Observables although now one requires the data right now? 🤔 Also we’re leaking the subscription as we never dispose.

Let’s fix this by subscribing and disposing to/from our Observables depending on if our Subject has a subscriber or not:

Image for post
Image for post

Woah, a lot of changes. Let’s go through it step by step.

When someone subscribes to our Subject by calling stateObservable()we call an action based on the subscription and disposal event. If this is the first subscriber to the Subject we also subscribe to the state Observable, if the last subscriber disposes from the Subject we also dispose from the state Observable, so we’re only subscribed when someone actually requests data.

Also, when the state changes, we now first check if we even have subscribers. If not, we do nothing, as the onSubscribeConsumer will later trigger the subscription to the internal Observable. Otherwise, for simplification, we just dispose from the current Observable and subscribe to the correct Observable for the new state.

Well, and that’s it already. Now we have a working data stream that changes the emission frequency based on the state, while any subscribers just stay subscribed.

Let’s put the parts quickly together and use the Emitter in a repository implementation:

grandcentrix

thoughts, stories and ideas | from the grandcentrix team |…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store