MVP (deprecated)
Last modified on Mon 20 Feb 2023


The Android team has moved past the MVP architecture and is now using MVVM on all new projects. We've kept this chapter as a reference since there is still a large number of projects that use the MVP structure. If you are starting a new project or refactoring the existing one, check the MVVM architecture setup described in the MVVM chapter.

MVP is short for Model-View-Presenter, and it is a derivative from the MVC (Model View Controller) design pattern. The main difference between the two is shown in the picture below.


What is MVP?

The MVP pattern is a way to separate background tasks from Activities/Fragments/Views to make the application simpler, code shorter, and maintainability better. MVP does all this by splitting the logic into three layers:

Why use MVP?

The main reason to use the MVP pattern is the KISS principle. Without using MVP, your Activity contains UI, UI logic, and data management. This means that there are many lines of code that are hard to maintain and cannot be reused. MVP splits complex tasks into multiple simpler tasks so they become easier to solve. Also, classes have less code, which means that they become much easier for your colleagues to maintain, debug and understand. MVP also allows unit testing because you can individually test each component of the app by recreating real use cases with mock data.


The Model is a representation of business logic or, to put it simpler, data that will be displayed in the user interface (view). It is implemented by the interactors that are responsible for some specific action (fetching data from the API, reading from a file...). After that, the result is sent to the presenter via listener.


The view is an interface that displays data (model) and is responsible for handling user input and invoking the corresponding method of the presenter. The view does only what the presenter tells it to do, and it shouldn't contain any logic.


The presenter is the “middle-man” and has references to the view and model. For instance, if your app needs to display the data of a user, the presenter would use its reference to a database business logic. From there, it would query a list of users and find the one it needs. Then, it would call a method in the view, passing the queried user, and the view would update the UI with the user data.


The listener is an interface implemented inside the presenter and used for retrieving data from the model. As the model is usually asynchronous, the presenter needs a way to listen when data is successfully fetched or when some kind of error happens. The listener is passed to the interactor as a method parameter, and it is not injected by Dagger like other components.

How to implement MVP?

Initial packages

public interface LoginView {

    void hideProgress();

    void showProgress();

    void showError(String message);
public interface LoginPresenter {

    void onLoginClick(String username, String password);
public interface LoginInteractor {

    void login(LoginListener listener, String username, String password);
public interface LoginListener {

    void onLoginSuccess (String message);

    void onLoginFail (String message);

MVP final packages

public class LoginActivity extends AppCompatActivity implements LoginView {

    Button loginButton;
    EditText usernameEditText;
    EditText passwordEditText;
    ProgressDialog progressDialog;

    LoginPresenter mPresenter;

    protected void onCreate(Bundle savedInstanceState) {
        loginButton = (Button) findViewById(;

    private void initializeView() {
        usernameEditText = (EditText) findViewById(;
        passwordEditText = (EditText) findViewById(;
                .loginModule(new LoginModule(this))

    private View.OnClickListener clickListener = new View.OnClickListener() {
        public void onClick(View v) {
            String username = usernameEditText.getText().toString();
            String password = passwordEditText.getText().toString();
            mPresenter.onLoginClick(username, password);

    public void hideProgress() {

    public void showProgress() {
        if (progressDialog == null) {
            progressDialog = ProgressDialog
                    .show(this, "Loading", "Please Wait", true, false);
        } else {

    public void showError(String message) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();

    public void navigateToSplash() {
        Intent intent = new Intent(this, SplashActivity.class);
public class LoginPresenterImpl implements LoginPresenter {

    private LoginView loginView;
    private LoginInteractor loginInteractor;

    public LoginPresenterImpl(LoginView loginView, LoginInteractor loginInteractor) {
        this.loginView = loginView;
        this.loginInteractor = loginInteractor;

    public void onLoginClick(String username, String password) {
        loginInteractor.login(listener, username, password);

    LoginListener listener = new LoginListener() {
        public void onLoginSuccess(String message) {

        public void onLoginFail(String message) {
public class LoginInteractorImpl implements LoginInteractor {

    LoginListener listener;

    public LoginInteractorImpl() {

    public void login(LoginListener listener, String username, String password) {
        this.listener = listener;

    private void startDummyLogin() {
        new Handler().postDelayed(new Runnable() {
            public void run() {
        }, 4000);

Useful links