Part 1: Reactive architectures. MVI + RxJava

Taras Morskyi
AndroidPub
Published in
6 min readFeb 12, 2019

TL;DR

MVI is a great pattern to use with RxJava. It allows you to get great event based reactive architecture which makes your code cleaner, more readable and easily scalable. Check out my repo to get an idea of reactive architecture I will describe in this article

Lucky hard workers

Fortunately, Google didn’t provide Android developers with patterns and general recommendations how to create good quality project till very recent moment. This situation forced us to find and create different tools for writing good quality code. Some of this tools are MVI and RxJava.

However, Google did something. Android applications are built in MVC pattern which actually is very similar to iOS’s one. It has layouts as Views, remote server or database as Model and Controllers which are Activities and Fragments. Why Google did not say us anything about it? Well, it was a very good decision. We had a chance to come up with solutions ourselves. Solutions for a problem which mostly all projects back in those days had: massive godlike Activities/Fragments with even 3–5k of lines (WOW?) easily. Some iOS developers even call it MMVC (Massive MVC).

To solve problem with huge Activities/Fragments an MVP pattern came to the rescue. It became so popular with very interesting idea — why don’t we look at Activity/Fragment as Views and business logic will be in different place (Presenter)? With this simple pattern code becomes more readable without those huge classes.

MVI — Model View Intent (not Android Intents, but some events, lets call it Event Manager and don’t mix with titles) — is a very similar pattern to MVP, but instead of having lots of methods you have just one public method, which is used by View and receives only one argument created in specific way to be able to identify every action.

Other great and very popular tool in Android community is RxJava. Even when a topic of this article is not to tell why RxJava is great (probably you already know it) but a few words about it to become clear with all approaches.

Reactive behaviours are built in mobile applications. You have a user who does some actions and you don’t know when exactly application will receive them, but it has to live all the time with this nescience and wait… and wait… and wait… and finally react. It is a good description why Reactive programming is a great tool to organise your reaction and combine them into chains of actions which have to be done to make user happy. Oh, did you think RxJava is great for making background tasks and get rid of Async Tasks, Threads, requests from IntentService or some other strange solutions for background parts of your project? You’re partially right, but it is just an additional feature to well organised streams and reactions.

Let’s react to some events

Now, when you have an understanding how to use RxJava in a better way we can combine it with MVI and react to our events. First of all, how to combine key parts of MVI with RxJava?

View

As was told before, in MVI pattern View is Activity/Fragment and it only handles callbacks from UI (ClickListeners, Lifecycle etc.) to send event to Event Manager and updates layout after receiving results from Event Manager. To make events reactive View implements Observer and creates subscription which will provide it with a stream of results and/or errors. All results are received in onNext().

Model

Model is the only common part in all patterns (MVC, MVP, MVI …… MVx) which is responsible for providing data from different sources like remote server or database. I will get to this part later with introduction of Clean Architecture by providing Interactors and Repositories as continuation of chains.

Event Manager (Intent)

Event Manager is the most complex and important part of architecture. Look back again on description of View: it receives events from Event Manager and it’s easy to understand that Event Manager is a place where we have Observable and View actually subscribes to exactly this Observable.

And what about events sent from View, Observable doesn’t receive any signals to call some next specific action, right? Here comes Subject which is an Observable and Observer at the same time. Now it’s clear how Event Manager receives events from View, handles them and sends back the result. View, on its lifecycle start and end subscribes and unsubscribes to Event Manager. When View needs to do some job from Event Manager it sends an event to a Subject. After receiving an event by Subject, it provides it to Event Handler (or just onEvent() function) which identifies received event to call required function from Model if it is required. After receiving result from Model it packs data required by View to send the result to its final Observer (View). If Model wasn’t called, it just sends required pack of data back to View.

CODE! WE NEED SOME CODE!

Reading theory is always painfully boring and now it is done, let’s get to the best part where I will keep talking about MVI parts with introducing those events I was talking all the time which are required for communication between main parts: View and Event Manager.

Event Model and UiModel

When we talk about events in MVI with RxJava we need two types of events:

  • Event Model which will be a representation of events sent from View to Event Manager
  • UiModel which will be a representation of results from Event Manager to View

With Kotlins sealed classes this Events are scalable and easy to identify.

Let’s look at this classes:

  • Both of them implement some Base classes which are just empty interfaces used for Generics in Event Manager and View
  • Every defined class (or object) describe an event or result with required fields for it.

Now when you know how those famous events look, let’s use them.

View

First of all, to use events in View requires an instance of Event Manager. You can create or inject it with Dagger2 in onCreate(), you decide. When Event Manager is ready to use, the first thing which has to be done is setting subscribing and unsubscribing to its Subject.

Now View is ready to send events and receive results to Event Manager.

As you can see, every time you need to do something View sends event to Event Manager for triggering a chain of actions in Event Manager which after doing its job sends result to its View. View, as it was already mentioned, is an Observer and receives results in onNext.

Event Manager

Event Manager, on the other hand, keeps Subject which is Observer and Observable. It means it has to deal with all those events by itself, and View is just its consumer. Let’s start by looking at Base implementation of Event Manager.

This class does not contain a lot of code, but still has some important parts:

  • Every Event Manager contains PublishSubject which receives only an instance of BaseEvent described with Generics
  • With attach() function View can subscribe to Event Manager. It also describes redirection to onEvent
  • Event(E) function is used for sending events from View to trigger a chain of actions in Subject. It also receives only an instance of BaseEvent described with Generics
  • onEvent(E) function which identifies and handles events received from View. It is also a source from where results for View are coming.

When BaseEventManager is ready to rock, what else is left to do in actual presenter? Not much. It requires only a definition of Generics and implementation of onEvent(E). Easy, right?

Right in the same way as it was in View, Event Manager identifies events received from View. But unlike View, Event Manager has to return an Observable with UiModel.

Interactor

Interactor, which was mentioned before, is a layer which has connection to Repositories (local database, remote server etc.) to get data from them. Also it is a class where you have to do all your data processing.

Conclusion

With this architecture you can use full power which RxJava gives you. Finally, you can forget about using RxJava for only wrapping your network requests. It may look like increase of code amount, but when you start using it you will understand what is the purpose of it and your code will become much more cleaner.

With ending of this part I want to thank Krystian Płoński for introducing to me into reactive architecture.

--

--