MVP Architecture for Android Applications
Android application development has come a long way, when I started app development 6 years ago; there weren’t any agreed upon practices/standards for developers to follow. The major flaw back then was the dependence on Activities and their lifecycles; apps at that time had major part of their code written in Activities, this was required because the code had to adhere to Activity’s lifecycle methods.
Several approaches were recommended by various architects who basically recommended moving out the code from Activities by separating responsibilities, various design patterns emerged namely MVC, MVVM and MVP.
We will talk about MVP in this article.
MVP provides us with ability to divide responsibilities of an app into different layers which follow SOLID principles, using this we break down our app into 3 layers Views, Presenters and Interactors.
Let’s look at the responsibilities of each layer.
- View: Activities, Fragments and other Android Views come into this layer, the general idea is that this layer has be very dumb, it shouldn’t know or be concerned about things like business logic or data layer logic of the application, the responsibility of this layer then is to just display the data to the user.
- Presenter: This layer should contain all the business logic of your app, the idea here is that there is one Presenter per View, so it can contain multiple Interactors each doing a singular functionality like getting a Data/Model from an API or from a DB and then processing it to better suit our requirements and pass it on to our View.
- Interactor: These are classes which are supposed to interact with data, this data can be gotten either from API’s or from a Database or from local App Cache, the idea here is that the Presenter will invoke a method from an Interactor for e.g. call a method named getData() and it should then provide that data to Presenter.
To understand this architecture we will look at a sample application which does the following.
Requirements of our App.
Allow a user to search for any movie by typing its ‘title’ in the search view of the Toolbar, the poster of the movie along with it’s title, IMDB rating and its plot will be shown to the user if query is successful and it will be saved to database, if a user enters the same title as he had before the data will not be fetched from the API but would rather be given from database.
Now let us look at the code, at the heart of this architecture we have GetMovieInteractor.java
Pay attention to getMovieForTitle() method, here we first query to see if there is an existing Movie in the database with the title we are querying for, if so we return it from database otherwise we call the API which will return the data from server, then depending on whether the result was successful or a failure we will pass the result to the Presenter, every Interactor will extend BaseInteractor.java, this class will help us manage our Subscriptions and is also responsible for attaching listeners from Presenter so that the data can be sent back to the Presenter, please refer to the Github project which is linked at the end of this article to know more about BaseInteractor.
Then we have a GetMoviePresenter.java which will call the method getMovieForTitle() from GetMovieInteractor and depending on the result call respective methods in the View, our GetMoviePresenter implements Presenter contract, the methods overridden by these callbacks will be called from Interactor.
Note subscribeInteractor() method which is overridden from BasePresenter, here we attach the listener for this Presenter to the Interactor so that it can send back results to this class, when a call to getMovieForTitle() from GetMovieInteractor is made, depending on the result either onGetMovieSuccess(), onError() and other methods are called, here the data has to be processed and sent to the View for the user to see. A View which will be calling this Presenter will first have to call subscribeView method of the Presenter which will in-turn call subscribePresenter method of Interactor, similarly there is a unsubscribeView method which should be called when the View is being destroyed, to view this code please refer to the Github repo linked at the end of this article.
GetMovieContract.java is a container interface where we define callbacks and separate them based on responsibility, each interface will have a View contract (depending on the expected results from a Presenter), API contract(which API is being called) and Presenter contract (callbacks to be called in Presenter from Interactor).
Finally we have the View in our case a Fragment named GetMovieFragment.java which implements our View contract.
GetMovieFragment is responsible for displaying data to the user and thus deals with only Android specific code like initializing Views, setting data onto them, hiding or showing Views based on result etc, apart from this the View does not know anything about how the data is fetched or other implementation details, notice subscribeView and unsubcribeView methods, these will attach our listener to the Presenter so that it can callback these methods when it has the data.
Observe how we divided responsibilities between View, Presenter and Interactor, as a direct result of this our code looks more organized, is testable and can be easily debugged for errors as we know the responsibility of each layer.
This concludes the article, in the next article I will demonstrate how to write Unit tests for this app.
I hope that with this tutorial I was able to effectively explain about MVP architecture with an example, please let me know what you think of my implementation and give suggestions in the comments below.
Senior Software Engineer — Mobile