MVP with RxJava2 + Room + Koin

Carlos Macías Martín
AndroidPub
Published in
5 min readFeb 13, 2019

In this article we’re going to create a Kotlin Android App following a clean architecture, using the MVP pattern and some useful libraries like RxJava2, Room and Koin in order to make the development easier to test and to maintain, as well as improve the decoupling of the code. Link to Github

Libraries configuration

In order to use these libraries, we must first import them with gradle, so in the buildscript section of our Project build.gradle we add:

And then, in our Module build.gradle we add:

That’s all about libraries configuration.

MVP Structure

We will follow the MVPI pattern:

To simplify the example, we’ll omit Use Cases and API connection.

The distribution of packages will be like this:

Entity

First of all, we must create an entity that we’ll use in the DAO (Data Access Object) needed by Room.

We give the entity Quote a table name for the DB, and then we specify te structure of that table in the constructor. The rest is self-explanatory.

DAO

Next we must create the DAO, where we define the interactions with the DB:

Here comes into action RxJava2. This library has support for Room DB operations, so we can return Single, Maybe, or Completable as responses from Insert, Update and Delete operations. As of version 2.1.0-alpha04 Room should also support it in @Query operations, but there is a bug that prevents it for now (as soon as alpha05 version is released, I will update this post).

Observable gives us the ability to constantly watch for changes in the list of quotes that there are on DB, like a live stream of data.

Note: If you don’t know what can Single, Maybe, or Completable do for you, take a look here.

Database

Now we create the Database class, in which we specify the entities that it’s going to contain, as well as the version of the DB. We’ll need to access the DAO through the DB so we add a function for this matter:

Repository

Now we have Room settled, it’s time to create the QuoteRepository. As we’ll use Koin for dependency inyection, we must first create an interface which QuoteRepository will implement:

And now we create QuoteRepository and implement the interface. In the constructor we pass QuoteDao, but this is where Koin does its thing, looking on its own for an instance of it:

We have omitted Update and Delete methods as they are pretty much the same as Insert.

In the insert() method we call the DAO insert method and pass it the Quote object we receive like parameter. Then we use .subscribeOn(Schedulers.io) to create a thread that’ll be executed on background. Then we call .observeOn(AndroidSchedulers.mainThread()) to specify in which thread we are going to watch for the result of this operation. Lastly, we call .subscribe() to execute the thread and define what it’s going to do depending on the response (success or error) returned by the DAO call.

As we talked earlier, we have a problem in deleteAllQuotes() method so we can not return a Completable. Thus, we are going to create a workaround with Completable.fromAction(), and, even though it’s not going to tell us if the DAO operation was successful or not, we will know if everything went well before reaching that point.

Finally getAllQuotes() will call DAO to get all the quotes from DB and return an Observable list of them.

Interactor

It’ll be responsible for connecting the Repository and the Presenter, as well as implementing the Business Logic (the Interactor should do that through Use Cases). To simplify, we just write a simple interface and the class:

And the class that implements it:

As you can see, the connection between modules (Repository-Interactor-Presenter…) is done by Koin constructor injection.

Presenter

It’s the module that will take care of telling the UI that something has changed.

First we must create the interface:

And the class that implements it:

It’s pretty much the same as before, except for the method loadQuotes() and that now getAllQuotes() will return a LiveData list of quotes instead of an Observable list. How does this work?

Well, we use RxJava2 in the method loadQuotes() to get the Observable list of quotes, and we assign that list to a MutableLiveData object that we will observe in the UI, our next step.

UI(View)

It will look like this:

You can get the code of the .xml layout here.

In the UI we will launch events and get notified of the results. For this, we create an activity:

The first line is the injection of the Presenter (must be a class that implements ViewModel() so Koin can look for the instance).

Then we call getAllQuotes() method that returns a LiveData list of quotes, and observe it specifying that every change on that list will reset the textView with the new data.

Next we call insert and delete methods in their respective onClickListener().

That’s all for the view.

Dependency Injection with Koin

Finally, we must tell Koin where it should look for the instances of the classes in order to inject them correctly. For this matter we create an AppModule file:

Database instantiation is done through Room.databaseBuilder().

DAO instantiation is done calling the quoteDao() method of AppDatabase, after getting its instance.

For repository and interactor we pass the class that implements their respective interfaces.

For presenter/viewModel we just call viewModel(), passing the presenter class that implements ViewModel().

Last step is to start Koin, and we can do that creating a MainApplication class:

Remember to add it to the manifest:

Now our app should work as expected, adding/deleting quotes and keeping data refreshed in every moment, even with device rotations.

I hope at this point you have learned how to write a clean MVP architecture. Feel free to fork the project and add your own ideas, like fragments, API client, etc. Thanks for reading! :)

--

--

Carlos Macías Martín
AndroidPub

I love developing mobile apps, and I’m an enthusiast about programming and new technologies. I enjoy helping people solve their problems and needs.