[Reprinted] Talking about MVP in Android

I. Overview

Most people can say a thing or two about MVP (Model View Presenter): "an evolutionary version of MVC", "completely decouple Model and View", etc. This blog post is just for the record, to put forward some opinions, and to help you how to write MVP-style code for an Activity page.

For MVP, I have a question in my heart:

Why can this model be accepted by the majority of Android programmers after it comes out?

 

Asked some programmers, and their general perception of MVP was: "The code is clear, but it adds a lot of classes". When I saw MVP for the first time, I watched a demo, and I felt very nice after reading it (but when I looked back and thought of an example to write, I had a headache and couldn't write it, of course, I will talk about it later). The reason for nice is because this mode does greatly improve the clarity of the code.

Then, the improvement is generally compared. Looking back, the code structure of MVP is not applied. Many people say that it is obviously MVC:

  • View: corresponds to the layout file
  • Model: business logic and entity model
  • Controllor: corresponds to Activity

It looks like that, but if you think about it carefully, this View corresponds to the layout file. In fact, there are very few things that can be done. In fact, the data binding operation and event processing code in the layout file are all in the Activity. , causing Activity to be both like View and Controller (of course, the emergence of Data-Binder may make View more like View). This may be why, in the article there is a sentence like this:

Most of the modern Android applications just use View-Model architecture,everything is connected with Activity.

When the architecture was changed to MVP, the Presenter appeared, and the Actvity was regarded as the View layer, and the Presenter was responsible for completing the interaction between the View layer and the Model layer. It now looks like this:

  • View corresponds to Activity and is responsible for drawing View and interacting with users
  • Model is still business logic and entity model
  • Presenter is responsible for completing the interaction between View and Model

ok, let’s take a brief look first, there will be examples in the text that can be intuitively felt at that time.

To sum up, that is to say, the reason why people feel refreshing is because this jump is a transition from 并不标准的MVCto to MVP, which reduces the responsibilities of Activity, simplifies the code in Activity, and extracts complex logic code into Presenter. to be processed. The corresponding advantage is that the coupling is lower and it is more convenient to test. Borrow two pictures (from: this article ) to represent the above transformation:

Into:

Second, the difference between MVP and MVC

ok, a bunch of theories are mentioned above, we still need to take a look at a difference between MVC and MVP, please see the following figure (from: this article ):

In fact, the most obvious difference is that in MVC, Model and View are allowed to interact, while in MVP, it is obvious that the interaction between Model and View is completed by Presenter. Another point is that the interaction between Presenter and View is through the interface (which will be reflected in the code).

There are still a bunch of conceptual things, and the advantages will be omitted, if you are interested in Baidu. The following shows how to write a demo of MVP through some simple requirements.

三、Simple Login Demo

Effect picture:

Seeing this effect, let's take a look at the project structure after completion:

ok, let's start writing the ideas step by step.

(1) Model

First of all, the entity class User does not need to consider this. Secondly, from the renderings, we can see that there is at least one business method login(). These two points are not difficult. We first complete:

package com.zhy.blogcodes.mvp.bean;

/**
 * Created by zhy on 15/6/18.
 */
public class User
{
    private String username ;
    private String password ;

    public String getUsername()
    {
        return username;
    }

    public void setUsername(String username)
    {
        this.username = username;
    }

    public String getPassword()
    {
        return password;
    }

    public void setPassword(String password)
    {
        this.password = password;
    }
}

 

package com.zhy.blogcodes.mvp.biz;

/**
 * Created by zhy on 15/6/19.
 */
public interface IUserBiz
{
    public void login(String username, String password, OnLoginListener loginListener);
}

 

package com.zhy.blogcodes.mvp.biz;

import com.zhy.blogcodes.mvp.bean.User;

/**
 * Created by zhy on 15/6/19.
 */
public interface OnLoginListener
{
    void loginSuccess(User user);

    void loginFailed();
}

 

Needless to say, as for the business class, we extracted an interface and an implementation class. This is also very common. The login method is generally connected to the server, which is a time-consuming operation, so we have opened up a sub-thread, Thread.sleep( 2000) simulates the time-consuming operation. Since it is a time-consuming operation, we notify the login status through a callback interface.

In fact, it is better to write here, because it is no different from the traditional writing method.

(2) View

As we said above, Presenter interacts with View through interfaces. So we need to define one here . The ILoginViewdifficulty lies in what methods should be used. Let's take a look at the renderings:

You can see that we have two buttons, one is login and the other is clear;

login indicates that there is a user name and password, then there are two methods:

String getUserName();

String getPassword();

 

In addition, login is a time-consuming operation, we need to give the user a friendly prompt, which is generally to operate the ProgressBar, so two more:
void showLoading();

void hideLoading();
 Of course, login has the processing of login success and failure. We mainly look at success, we are jumping Activity, and failure may be a reminder:
void toMainActivity(User user);

void showFailedError()
 ok, we have finished analyzing the login method~~ There is only one clear left, which is simple:
    void clearUserName();

    void clearPassword();
 In summary, the complete interface is:
package com.zhy.blogcodes.mvp.view;

import com.zhy.blogcodes.mvp.bean.User;

/**
 * Created by zhy on 15/6/19.
 */
public interface IUserLoginView
{
    String getUserName();

    String getPassword();

    void clearUserName();

    void clearPassword();

    void showLoading();

    void hideLoading();

    void toMainActivity(User user);

    void showFailedError();

}
 

With the interface, the implementation is very easy to write~~~

To sum up, for the View interface, observe the functional operation, and then consider:

  • What does this operation require? (getUserName, getPassword)
  • The result of the operation, the corresponding feedback? (toMainActivity, showFailedError)
  • The corresponding friendly interaction during this operation? (showLoading, hideLoading)

Let’s paste the implementation class of our View below. Ha, it is actually an Activity. As mentioned at the beginning of the article, the View in MVP is actually an Activity.

package com.zhy.blogcodes.mvp;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.zhy.blogcodes.R;
import com.zhy.blogcodes.mvp.bean.User;
import com.zhy.blogcodes.mvp.presenter.UserLoginPresenter;
import com.zhy.blogcodes.mvp.view.IUserLoginView;

public class UserLoginActivity extends ActionBarActivity implements IUserLoginView
{


    private EditText mEtUsername, mEtPassword;
    private Button mBtnLogin, mBtnClear;
    private ProgressBar mPbLoading;

    private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate (savedInstanceState);
        setContentView(R.layout.activity_user_login);

        initViews();
    }

    private void initViews()
    {
        mEtUsername = (EditText) findViewById(R.id.id_et_username);
        mEtPassword = (EditText) findViewById(R.id.id_et_password);

        mBtnClear = (Button) findViewById(R.id.id_btn_clear);
        mBtnLogin = (Button) findViewById(R.id.id_btn_login);

        mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading);

        mBtnLogin.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mUserLoginPresenter.login();
            }
        });

        mBtnClear.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                mUserLoginPresenter.clear();
            }
        });
    }


    @Override
    public String getUserName()
    {
        return mEtUsername.getText().toString();
    }

    @Override
    public String getPassword()
    {
        return mEtPassword.getText().toString();
    }

    @Override
    public void clearUserName()
    {
        mEtUsername.setText("");
    }

    @Override
    public void clearPassword()
    {
        mEtPassword.setText("");
    }

    @Override
    public void showLoading()
    {
        mPbLoading.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading()
    {
        mPbLoading.setVisibility(View.GONE);
    }

    @Override
    public void toMainActivity(User user)
    {
        Toast.makeText(this, user.getUsername() +
                " login success , to MainActivity", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showFailedError()
    {
        Toast.makeText(this,
                "login failed", Toast.LENGTH_SHORT).show();
    }
}

 

It is very easy to implement the interface we defined above in Activity, after all, the interface guides us to complete it.

Finally see our Presenter.

(3) Presenter

Presenter is used as a bridge for interaction between Model and View, so what should be the method?

In fact, it mainly depends on what operations this function has. For example, in this example, there are two operations: login and clear.

package com.zhy.blogcodes.mvp.presenter;

import android.os.Handler;

import com.zhy.blogcodes.mvp.bean.User;
import com.zhy.blogcodes.mvp.biz.IUserBiz;
import com.zhy.blogcodes.mvp.biz.OnLoginListener;
import com.zhy.blogcodes.mvp.biz.UserBiz;
import com.zhy.blogcodes.mvp.view.IUserLoginView;


/**
 * Created by zhy on 15/6/19.
 */
public class UserLoginPresenter
{
    private IUserBiz userBiz;
    private IUserLoginView userLoginView;
    private Handler mHandler = new Handler();

    public UserLoginPresenter(IUserLoginView userLoginView)
    {
        this.userLoginView = userLoginView;
        this.userBiz = new UserBiz();
    }

    public void login()
    {
        userLoginView.showLoading();
        userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener()
        {
            @Override
            public void loginSuccess(final User user)
            {
                //Need to be executed on UI thread
                mHandler.post(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        userLoginView.toMainActivity(user);
                        userLoginView.hideLoading();
                    }
                });

            }

            @Override
            public void loginFailed()
            {
                //Need to be executed on UI thread
                mHandler.post(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        userLoginView.showFailedError();
                        userLoginView.hideLoading();
                    }
                });

            }
        });
    }

    public void clear()
    {
        userLoginView.clearUserName();
        userLoginView.clearPassword();
    }



}

 

Pay attention to the above code, our presenter completes the interaction between the two, so the implementation class of the two must be required. Roughly, it is to get the required parameters from the View, hand it over to the Model to execute the business method, the feedback required in the execution process, and the results, and then let the View to display the corresponding results.

ok, get an example and basically complete it after the above decomposition. The above is purely personal opinion, welcome to discuss and complain ~ have a nice day ~.

References

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327060648&siteId=291194637