Building Android applications is fun and challenging. We at SocialCops built Collect — a mobile-based data collection tool, currently being used by nearly 150 organizations around the world. The ever-increasing number of users, encouraging as it is, made it difficult to scale up Collect with the existing code structure.
That was when we decided to move to the Model-View-Presenter (MVP) design pattern to solve the existing scale-related issues in Collect and, most importantly, improve the core functionality of the app — data collection.
What Is the MVP Pattern?
The MVP Pattern is a software design pattern commonly used for developing Android applications. It has gained importance over the last couple of years due to the need for developing clean applications that are easy to scale, test and maintain. The MVP pattern fills this need by enabling the development of highly decoupled applications.
Why Use the MVP Pattern?
In a typical Model-View design pattern, the views and data layers of the application are tightly coupled and hence there is no layer of abstraction between the two layers. Therefore, for all practical purposes, there is only one layer handling both the views and their interaction with different data sources. This leads to redundancy in code and difficulty in scaling.
To overcome all the above drawbacks of a tightly coupled design, the MVP Pattern is used.
It is always a good practice to separate the data layer from the views of the app. The data can then be modeled separately in a different layer to cater to multiple views.
- Easy Data Modeling: It is always a good practice to separate the data layer from the views of the app. The data can then be modeled separately in a different layer to cater to multiple views. This is where the presentation layer comes in handy.
- Easy Debugging: By creating three different layers of abstraction it becomes easier to test and debug each layer in isolation and narrow the source of a bug down to one of the three layers.
- Increased Code Re-usability: The developer has to write a lot less code because a single data source serves all the views. This saves bandwidth since similar data doesn’t have to be queried more than once.
Layers in the MVP Pattern
Let’s dissect the architecture to look at the functions and components of each layer and how they interact with each other.
The View Layer is only responsible for handling different views visible to the user, such as activities, fragments, and dialogs.
This is the only layer that consists of different Android components and is completely orchestrated by the Presentation Layer. The View Layer delegates all the user events that occur on it to its corresponding presenter and then waits for the presenter to respond with the appropriate data.
The Presentation Layer, aka the Presenter, holds all the business logic for the application. It acts as a channel of communication between the View Layer and the Data Layer.
The Presenter too has its own interface through which both the View and Data Layers communicate.
The View Layer delegates all the events that occur on the device’s screen to the Presentation Layer. The Presenter interprets each event as a data requirement. It then fetches the required data from the Data Layer, models it, and presents it to the View Layer.
Unlike the Data Layer, the Presentation Layer is not common to the whole application and is different for each view on the mobile device. The Presenter cannot communicate with views other than its own and vice versa.
The Data Layer is responsible for all the data requirements of the application.
It consists of 4 different components:
- CRUD operations from a locally embedded database
- Data storage and retrieval from the device’s internal/external memory
- Network and API calls
- Different entity models
Each component has an interface associated with it. The interface acts as a gateway between the Presentation Layer and the Data Layer. Each interface consists of method declarations that are implemented by their respective components.
Bringing All Layers of the MVP Pattern Together
Here’s a graphic representation of how all three views come together in the broader architecture:
A good practice to move data objects between different layers is through using listeners and not making methods return data objects.
Testing Apps Built Using the MVP Pattern
Building your application in 3 different layers helps you to test each layer in isolation. Moreover, with the MVP Pattern, testing can be automated to a large extent. There are libraries available to make this process easy for you.
Testing is mainly divided into two parts:
- Unit Testing: used for testing the Presentation and Data Layers
- Instrumentation Testing: used for testing the View Layer
Unit testing for the Presentation Layer and the Data Layer can be done on the JVM (Java Virtual Machine) itself and does not require any device. This is because both these layers are completely written in native Java and do not contain any Android concepts. Since the Presenter interacts with the view through an interface, the presenter treats the view as an abstract concept and does not have any knowledge of Android components in the view. At SocialCops, we use JUnit4 for writing unit tests.
Instrumentation tests are done for the View Layer, which requires an Android device. We use Espresso to write instrumentation tests.
You might be wondering about how we test each layer in isolation without requiring input from the other two layers. For this, we use Mockito to make mock objects in Java.
The MVP Pattern is an important design pattern for developing Android applications. It helps developers build scalable, maintainable, and test-ready applications without any extra effort.
Initially, it might seem pretty difficult during implementation since you, as the developer, will have to create different classes and interfaces for each layer. However, once you get the hang of it, trust us that it will be your go-to way of developing elegant Android applications.
You have got a really nice blog related to the MVP pattern, it has got useful information that a noob or a person who is confused related to it.
Very nice blog.
“Unit testing for the Presentation Layer and the Data Layer can be done on the JVM (Java Virtual Machine) itself and does not require any device. This is because both these layers are completely written in native Java and do not contain any Android concepts”
what do you mean by this? My data layers does have firebase function calls. Is my implementation wrong?
This is a very good article to start building Android apps in a cleaner way and is always expected to behave the way MVP pattern thinks. However, the real deal breaker is how your app evolves, which I think is the case for collect as of now. Frankly, for starters MVC, MVVP etc would also behave in the same way.
Here’s the article highlighting important steps while your app evolves, eventually moving towards Reactive pattern:
1) Focusing on Observables and Subscribers (which helps in data transformation without needing to go change your client code every now and then)
2) Modular Async Tasks
3) Modular Error Handling
4) Smart Build modifications which leads to easier Packaging.
Hey Tanay, this method sounds cool and interesting. I’ll inform all my developer friends and persons in network to read it. Keep sharing more tips. 🙂