MVP Deep Dive

Budhdi Sharma
AndroidPub
Published in
7 min readJan 17, 2020

--

MVP design pattern

In this blog, we are going to discuss the MVP Design Pattern for Android which is a better and modified alternative to MVC.

Note: I am trying to make this (MVP) concept as easy as possible because everyone might have different opinions on MVP. So, do not get confused because it is simply a design pattern to write our code in a more readable and segregated manner. The main concepts we are going to learn are how the Model, View, and Presenter are interlinked and to get familiar with this. You can implement this design pattern in your own way.

There have been breaking changes about architectural patterns since then, such as MVVM with architecture components, but MVP is still valid and an option to take into account.

What is MVP?

The MVP pattern allows separating the presentation layer from the logic so that everything about how the UI works is agnostic from how we represent it on screen. Ideally, the MVP pattern would achieve that the same logic might have completely different and interchangeable views.

The first thing to clarify is that MVP is not an architecture by itself, it’s only responsible for the presentation layer. This has been a controversial assessment, so I want to explain it a bit deeper.

You may find that MVP is defined as an architectural pattern because it can become part of the architecture of your App, but don’t consider that just because you are using MVP, your architecture is complete. MVP only models the presentation layer, but the rest of the layers will still require good architecture if you want a flexible and scalable App.

An example of a complete architecture could be Clean Architecture, though there are many other options.

In any case, it is always better to use it for your architecture that not using it at all.

Why use MVP?

In Android, we have a problem arising from the fact that Android activities are closely coupled to both UI and data access mechanisms. We can find extreme examples such as CursorAdapter, which mixes adapters, which are part of the view, with cursors, something that should be relegated to the depths of the data access layer.

For an application to be easily extensible and maintainable, we need to define well-separated layers. What do we do tomorrow if, instead of retrieving the same data from a database, we need to do it from a web service? We would have to redo our entire view.

MVP makes views independent from our data source. We divide the application into at least three different layers, which lets us test them independently. With MVP we take most of the logic out from the activities so that we can test it without using instrumentation tests.

VIEW

The View part of MVP contains the visual parts of our application, like showing messages and also handles visibility. The view contains only that part of the code which is related to UI and it does not contain any logic related to the displayed data. The View is controlled by the Presenter.

The view is simply a java class that is responsible for making changes in the User Interface (UI). For example, change in the text of a TextView, change in text size of an EditText, change in color of a Button or any other User Interface related change. In Android, an Activity, Fragment or any other component that can change the visual presentation is referred to as View. Phew! That was a secret.

Since we are talking about implementation, I must say, to follow MVP’s principle of maintainability and testability a View interface must be defined. This interface contains method declarations associated with changes in visual representation. Activity or Fragment should implement this interface to define the complete functionality. Using this approach allows us to pass just an abstract implementation wherever required and can easily be mocked.

MODEL

The model will continue to contain the data in simple classes, so nothing really changes here.

Everything which is related to data is a part of the Model. The Model contains a data provider and the code which fetches and updates the data. This part of MVP updates the database or communicates with a web server.

So what’s a Model? As the name suggests, has it anything to do with some structure? Again, the Model is the component that is responsible for getting data in the app. The methods are declared in a separate interface which is defined keeping in mind the maintainability and testability of MVP’s principles. Yes! That’s it.

For making a concrete concept of what a Model is, it’s necessary to know the common data access patterns of app development. If we see on a broader level, an app fetches data from some REST API and stores in the persistent storage for easy access in the absence of network connection. An app must provide a coherent experience in the present as well as in the absence of a network. So for providing a consistent experience, a Model must include methods for fetching, inserting, modifying or deleting data which should remain common for both network scenarios, i.e. no matter what the network state is using Model’s method the app can get relevant data.

The model is divided into different parts. The parts may vary as per the required implementation but basically these consist of local database handling, network APIs handling (for getting data from web service) and preferences management. These individual parts manage the logic for getting data and giving back to the presenter.

The API Manager, the Database Manager, and the Preference Manager contain logic for providing data to the presenter and taking data from the presenter and storing it. Separate interfaces are defined for each of these and are implemented. These interfaces are created to avoid passing the concrete implementation of these classes hence making the testing area-wide.

PRESENTER

The Presenter contains the application’s business logic and when an operation is performed or data is changed then it will notify the View that it needs to update.

The Presenter. It’s the one that connects all the other components together. It’s a class having the working logic of the complete application. An activity or fragment which is the View should pass data to the Presenter and it’s the responsibility of the Presenter to handle it. The View interacts with the Presenter by calling its functions. The functions are declared in a separate interface and the same is implemented in the Presenter. The presenter has basically three important functions:

  1. Perform any viable logical operations on the data provided.
  2. Store or get the data from database or preferences via Model.
  3. Alter the state of the View.

The Presenter should not contain any Android-specific components like Context, Activity, Fragments, etc. They make testing hard.

This is how the MVP is implemented but the implementation styles vary based on coding style and requirements.

How Model, View, Presenter are created?

“Some of this makes sense. But how these MVPs are created?” An abstract idea of MVP is presented until now, thinking of the creation of these will add more juice to it. Naturally, any of these components are not pre-existing in the Android framework. If we put some thought, View is the component that is closely related to Activity and Fragments, and these are the core components of Android.

An activity creates a Presenter. The presenter takes in View and Model as arguments for getting the job done.

A simple example of a user login made with the MVP design pattern.

/*The Interface LoginPresenter.*/
public interface LoginPresenter{
/*when user click on login button from Activity*/void handleLogin(String username, String password);
}
************************************************************
/*The Interface LoginView.*/
public interface LoginView {
void showValidationErrorMsg();
void loginSuccessFully();
void loginFail();
}
*************************************************************/* Class LoginPresenterImpl.*/public class LoginPresenterImpl implements LoginPresenter {
private LoginView loginView;
public LoginPresenterImpl(LoginView loginView){
this.loginView = loginView;
}
@Override
public void handleLogin(String username, String password)
{if ((TextUtils.isEmpty(username) || TextUtils.isEmpty(password)){
loginView.showValidationErrorMsg();
}
else{
if (username.equals("Standerd") && password.equals("Standerd"))
{
loginView.loginSuccessFully();
}
else{loginView.loginFail();
}
}
}
}

*******************************************************************
/* Main Activity Class.*/
public class MainActivity extends AppCompatActivity implements LoginView{
private LoginPresenter presenter;
private TextView textViewUserName;
private TextView textViewPassword;
private Button buttonLogin;
@Overrideprotected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeView();
presenter = new LoginPresenterImpl(this);
buttonLogin.setOnClickListener(new View.OnClickListener() {
@Overridepublic void onClick(View v) {
presenter.handleLogin(textViewUserName.getText().toString(), textViewPassword.getText().toString());
}
});
}
private void initializeView()
{
textViewUserName = findViewById(R.id.textViewUserName);
textViewPassword = findViewById(R.id.textViewPassword);
buttonLogin = findViewById(R.id.buttonLogin);
}
@Override
public void showValidationErrorMsg()
{
Toast.makeText(this, "Username or Password is incorrect", Toast.LENGTH_SHORT).show();
}
@Override
public void loginSuccessFully(){
Toast.makeText(this, "Login SuccessFully", Toast.LENGTH_SHORT).show();
}
@Overridepublic void loginFail()
{
Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
}

Please checkout the Github code if you want to take full src from the below link.

RISK OF MVP

most important we use to forget is that the presenter is attached to the view forever. And the view is an activity, which means that:

  • We can leak the activity with long-running tasks
  • We can try to update activities that have already died

For the first point, if you can ensure that your background tasks finish in a reasonable amount of time, I wouldn’t worry much. Leaking an activity 5–10 seconds won’t make your App much worse, and the solutions to this are usually complex.

The second point is more worrying. Imagine you send a request to a server that takes 10 seconds, but the user closes the activity after 5 seconds. By the time the callback is called and the UI is updated, it will crash because the activity is finishing.

To solve this, we call the onDestroy() the method that cleans the view:

That way we avoid calling the activity in an inconsistent state.

fun onDestroy() {

loginView = null;

}

Conclusion

Separating interface from logic in Android is not easy, but the MVP pattern makes it easier to prevent our activities end up degrading into very coupled classes consisting of hundreds or even thousands of lines. In large Apps, it is essential to organize our code well. Otherwise, it becomes impossible to maintain and extend.

Nowadays, there are other alternatives like MVVM, and I will create new articles comparing them and helping with the migration. So keep tuned!

Android Developers Android Android 1833roid Xyz Zyx

Thanks for the support!

I hope you enjoyed this session. If you have any comments or questions, please join the forum discussion below!

--

--

Budhdi Sharma
AndroidPub

As an AOSP developer, I specialize in creating robust framework and system applications that seamlessly integrate with embedded systems on various SOCs