There are a lot of basic knowledge about MVP on the Internet, but most of them are just demos. After all, there are countless debugging between Demo and actual application. In fact, I also read a lot of introductions about MVP at the beginning, including official Google Demo and many technical blogs, and I thought I knew what MVP was at that time. Later, when I really applied it in my own project, I found that it was not so simple. However, after some torments, I gradually had a deeper understanding of MVP, so I would like to share it with you today.

MVP structure Diagram

I drew a diagram, which is the simplest structure of MVP. I won’t explain MVP here. Today I want to translate all the knowledge into code, which is the diagram in the diagram.

M layer

  • Here M layer is not in the traditional sense of the Model, I tend to think he is a ModelManager, is a data processing center, can deal with online data, databases, files, and interaction of the four components of the Android contains BroadcastReceiver, in Service, For a long time, MY cognition of M was that it was an entity class. At that time, I thought I had a good grasp of M, but finally I found that my understanding was wrong. MddelManager holds the reference of Presenter. The Presenter can Callback to the View because it holds a reference to the View

V layer

  • A V is a View, which can be an Activity or Fragemnt, or a Dialog, Toast, or Snakbar. Specifically, a View interacts directly with the user. The View implements the Callback interface and passes it to the Presenter. The Presenter then goes to the ModelManager to interact with it, and when the data is processed, it is called back via Callback, completing a closed loop

P

  • P is for Presenter, it is a guest role, it is like a bridge between the Vie and the Modelmanager. Many articles deal with logic in the Presenter, I think it is not very good, I think it is better in the Modelmanager. This decoupling is more complete, because a Presenter is only a messenger in the middle and should not deal with too much logic.

The relationship is clear, in fact, the code implementation is relatively simple

M layer code

public class MainManager {
    private ViewCallBack mViewCallBack;

    public MainManager(ViewCallBack viewCallBack) {
        this.mViewCallBack = viewCallBack;
    }

    public void getData() {
        mViewCallBack.refreshView(1, "Data"); }}Copy the code

This is just a template, maybe an interface needs a variety of data processing methods, so according to the needs in the redefine several methods can be

V layer code

Public interface ViewCallBack<V> {/** * @param code:0; Void refreshView(int code, V data); void refreshView(int code, V data); }Copy the code

The reason why V is generic here is that each interface needs to obtain different data, so it is differentiated by generics. When an interface needs to obtain many interfaces, or the data result types are not consistent, the generics here need to be specified by Object. The refreshView is then used to determine which data needs to be refreshed based on the data type

P code

public class MainPresenter {
    private ViewCallBack mViewCallBack;
    private MainManager mMainManager;

    public MainPresenter(ViewCallBack viewCallBack) {
        this.mViewCallBack = viewCallBack;
        mMainManager = new MainManager(mViewCallBack);
    }

    public void getData() { mMainManager.getData(); }}Copy the code

The methods in the P layer code correspond to the Manager, and then handle the M layer and V layer Callback, but note that Presenter is an object and needs to be null when the interface is destroyed to prevent memory leaks

In the demo I just wrote a simple change to Text, of course you can do anything you want in the Manager, because it’s an interface callback, run it and see what it looks like

MVP rendering

Continue to encapsulate

The above is just a Demo, and the following is a wrapper extraction for easy integration into a real project

  1. M layer encapsulation
public abstract class BaseBeanManager {

    protected ViewCallBack mViewCallBack;
    protected HashMap<String, String> paramMap;

    public BaseBeanManager(ViewCallBack modelCallBack) {
        mViewCallBack = modelCallBack;
    }
    public abstract void getData();
}Copy the code
  1. V layer encapsulation
public abstract class BaseActivity<T extends BasePresenter, V> extends AppCompatActivity implements ViewCallBack<V> { public T presenter; Version_codes.m) @override protected void onCreate(Bundle Bundle) { super.onCreate(bundle);setContentView(getLayoutId());
        presenter = initPresenter();
        initViews();
        initListener();
    }

    @Override
    protected void onResume() { super.onResume(); // Initialize Presenterif(presenter == null) presenter = initPresenter(); // Add ((ViewCallBack) this); } protected abstract int getLayoutId(); protected abstract void initViews(); protected abstract void initListener(); // Initialize the listening event protected abstract initPresenter(); // Initialize Presby@override protected voidonDestroy() { super.onDestroy(); // Destroy callback and null Presenter at the end of the lifecycleif(presenter ! = null){ presenter.remove(); presenter = null; }}}Copy the code
  1. P layer encapsulation
public abstract class BasePresenter { protected BaseBeanManager mBeanManager; // Define base class manager protected HashMap<String, String> paramMap = new HashMap<>(); protected ViewCallBack mViewCallBack; public BasePresenter(ViewCallBack viewCallBack) { mViewCallBack = viewCallBack; } public void add(ViewCallBack viewCallBack) { this.mViewCallBack = viewCallBack; } public voidremove() { this.mViewCallBack = null; } // the default method to getData is protected. }Copy the code

use

  1. M layer
public class MainManager extends BaseBeanManager {

    public MainManager(ViewCallBack modelCallBack) {
        super(modelCallBack);
    }

    public void getData() {
        mViewCallBack.refreshView(1, "Data returned by MVP."); }}Copy the code

2. V layer

public class MainActivity extends BaseActivity<MainPresenter, String> implements ViewCallBack<String> {
    private TextView tvDemo;
    private Button btnGet;
    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initViews() {
        tvDemo = (TextView) findViewById(R.id.tv_demo);
        btnGet = (Button) findViewById(R.id.btn_get);
    }

    public void initListener() {
        btnGet.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { presenter.getData(); }}); } @Override protected MainPresenterinitPresenter() {
        returnnew MainPresenter(this); } @Override public void refreshView(int code, String data) { tvDemo.setText(data); }}Copy the code
  1. P
public class MainPresenter extends BasePresenter {

    public MainPresenter(ViewCallBack viewCallBack) {
        super(viewCallBack);
    }


    public void getData() { mBeanManager = new MainManager(mViewCallBack); mBeanManager.getData(); }}Copy the code

I don’t want to post so much code, but only by comparison can I find out that MVP is completely decoupled, so it meets the principle of single responsibility. After encapsulation, even though more classes are created, each class needs a corresponding Presenter, but the amount of code is very small, so it seems logical

This is the MVP that I am using in my project. At the beginning, I was not used to it when I converted from MVC, but after a while, I found it was actually quite useful.

Project Download Address