Android Architecture

Android MVP Architecture for Beginners (Demo App)

Android MVP Architecture is address the common difficulties such as maintainability and testability. So in this article, We will discuss the various difficulties that address by Android MVP Architecture

What is MVP ..?

MVP (Model View Presenter) design pattern is derived from MVC pattern most of the things is same, where is the controller is replaced by presenter. The MVP design pattern is set of guidelines that should follow for better code reusability and testability. As per MVP guidelines application divided into three part Model, View Presenter.

Key point of MVP design pattern

  • MVP pattern addresses the common difficulties in android app, especially problem is related to maintainability and testability.
  • Model View Presenter increases the view separation of the concern and facilitated unit testing .
  • In the MVP pattern, we can separate background task from activity, fragment views to make them independent of most life cycle related event   
  • Using a consistent architectural and design pattern the development process become much more consistent, a lot of easier and transparent.
  • This way the application become more simpler, overall application reliability increases remarkable. The application code become cleaner and readable. Code maintainability become better and most importantly becomes fun and developer are Happy 🙂 .

How MVP work ?

The MVP pattern is user interface software architecture pattern that reduces the behavior of UI component. In this case, it reduces the interaction with Activity and Fragments bare minimum by using Presenter. The Pressenter simply a controller like class to handle presentation logic and update view accordingly.  Using presenter we can write business logic in presenter layer that have minimum interaction with views that make much easier to test and much faster to test. Why it makes faster to test, well simply put we no longer need to test input and output. the android content is gone so we no need of android emulator and device, We just need on JVM for running test which is quite fast.

Flow of MVP work ?

MVP in android

Just review the above figure that give explanation How MVP is work. Suppose they have shown some user information with couple of variable like first and last name.  The user makes change in first and last name and save the information on by clicking on save button. In this state the presenter will be involved by obtaining first and last name, now presenter will check these are valid or not. If value invalid then presenter makes the error and show the error message on the view. However, the case value is correct the update the model and send callback to view showing updated value on the views.

The Robert C Martin say in A Handbook of Agile Software Craftsmanship – The one way to make deadline – the one way to go fast – Is the keep the code as clean as possible all times.

Layer of MVP architecture – Model,View and Presenter

Model

In the clean architecture each layer have own models and models contains data relevant only  to that layer.

For example

  • View have own ViewModel to present data in the view      
  • Database Model may be need to retrieve database entity
  • Simliery Network model may be to needed represent data entries to retrieve from remote server
  • When data move between layer – the Model is transformed from  one layer representation layer to another. 

Presenter

A Presenter is a  middle man between views and Model , It is also contain business logic to the presentation of data .

The Presenter the retrive the data from model and format the data before passing the view . The Presenter also update the UI via View.

View

In MVP design pattern The Activity and Fragment and View is passive and can not access model directly, The view have reference of the presneter and propagate the event UI to Presenter. For example onClick event lifecycle event etc, ,

The Views is expose methods which control presentattion of  data or model for instance show or hide certain element.

Few important things keep in mind while using any design pattern .

As per clean architecture – One layer must be depend on the layer below

  • View depend on presenter and presenter must be depeded on use case
  • Code can not jump over the such as view can not access the use case  and presenter can not access the enity
  • Remarkable thing Dependency is followed downward see the flow diagram

MVP Sample App

Now we will a sample app following a MVP design pattern. Open Android Studio and create a new project. Enter project name like MVP example and select empty template and change activity name as LoginActivity .

Open activity_login.xml and add below code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="@dimen/_8dp">


    <EditText
        android:id="@+id/loginActivity_firstName_editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="First Name"
        tools:text="First Name" />

    <EditText
        android:id="@+id/loginActivity_lastName_editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Last Name"
        android:layout_marginTop="@dimen/_8dp"
        tools:text="Last Name" />

    <Button
        android:id="@+id/loginActivity_login_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:textColor="@color/colorWhite"
        android:layout_marginTop="@dimen/_16dp"
        android:text="Log in" />

</LinearLayout>
Add dimens value in dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="_16dp">16dp</dimen>
    <dimen name="_8dp">8dp</dimen>
    <dimen name="default_padding">4dp</dimen>
</resources>

Create a model class with named User.Java , which hold some user properties with getter setter such as id, first name, last name

package com.wave.mvpexample.data.model;

public class User {

    private int id;
    private String firstName;
    private String lastName;

    public User(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }


    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }


    public String getLastName() {
        return lastName;
    }

}
For using MVP design pattern, Now I create login contract interface. Just create a new interface inside src folder and add below code
package com.wave.mvpexample.login;

import com.wave.mvpexample.data.model.User;

public interface LoginActivityMVP {

    interface View{

        String getFirstName();
        String getLastName();

        void showInputError();

        void setFirstName(String firstName);

        void setLastName(String lastName);

        void showUserSavedMessage();
    }

    interface Presenter {

        void setView(View view);

        void loginButtonClicked();

        void getCurrentUser();

    }

    interface Model {

        void createUser(String name, String lastName);

        User getUser();

    }
}

Create a model named is LoginModel

Just create a new class java which implements LoginActivityMVP.Model and add below code

package com.wave.mvpexample.data.model;

import com.wave.mvpexample.data.repo.LoginRepository;
import com.wave.mvpexample.login.LoginActivityMVP;

public class LoginModel implements LoginActivityMVP.Model {


    private LoginRepository repository;

    public LoginModel(LoginRepository repository) {
        this.repository = repository;
    }

    @Override
    public void createUser(String name, String lastName) {


        repository.saveUser(new User(name, lastName));


    }

    @Override
    public User getUser() {

        return repository.getUser();
    }
}
Create a Repository for playing model

In LoginModel you see we are using a LoginRepository. To create a new interface which provides user instance and save the user instance in the repository.

package com.wave.mvpexample.data.repo;

import com.wave.mvpexample.data.model.User;

public interface LoginRepository {

    User getUser();

    void saveUser(User user);
}
Let’s create a repository named is UserRepository

Now create a java file which implements LoginRepository and add block of code

package com.wave.mvpexample.data.repo;

import com.wave.mvpexample.data.model.User;

public class UserRepository implements LoginRepository {

    private User user;

    @Override
    public User getUser() {

        if (user == null) {
            User user = new User("Dinesh", "Kumar");
            user.setId(0);
            return user;
        } else {
            return user;
        }

    }

    @Override
    public void saveUser(User user) {

        if (user == null) {
            user = getUser();
        }

        this.user = user;

    }
}
Create Presenter for LoginActivity

As per MVP, we have created Model, View on above, Now we will create a presenter for LoginActivity, Just create a java class with named is LoginActivityPresenter which implementing LoginActivityMVP.Presenter. In presenter we are doing the following operation.

  • Pass the view instance in the presenter in setView(View mView) methods
  • Defining onClick() event in loginButtonClicked() methods
  • Body on getCurrentUser() methods is retruning user instance
package com.wave.mvpexample.login;

import android.support.annotation.Nullable;

import com.wave.mvpexample.data.model.User;

public class LoginActivityPresenter implements LoginActivityMVP.Presenter {

    @Nullable
    private LoginActivityMVP.View view;
    private LoginActivityMVP.Model model;

    public LoginActivityPresenter(LoginActivityMVP.Model model) {
        this.model = model;
    }

    @Override
    public void setView(LoginActivityMVP.View view) {

        this.view = view;

    }

    @Override
    public void loginButtonClicked() {

        if (view != null) {
            if (view.getFirstName().trim().equals("") || view.getLastName().trim().equals("")) {
                view.showInputError();
            } else {

                model.createUser(view.getFirstName(), view.getLastName());
                view.showUserSavedMessage();

            }

        }

    }

    @Override
    public void getCurrentUser() {

        User user = model.getUser();

        if (user != null) {
            if (view != null) {
                view.setFirstName(user.getFirstName());
                view.setLastName(user.getLastName());
            }
        }

    }
}

I have distributed project in different packages. So all project structure looks like below figure.

 Android MVP Architecture for Beginners
MVP Project Structure

Open LoginActivity and implements LoginActivityMVP.View