Let’s look at MVC before we look at MVP

MVC

The full name of MVC is Model View Controller, which is the abbreviation of Model, View and Controller. It is a method of separating business logic, data and interface display to organize code and gather business logic into a component. There is no need to rewrite business logic while improving and customizing interfaces and user interactions.

  • Model: The data layer, which handles business logic and listens to network or database interfaces;
  • View: Interface (UI) layer, which displays data from Model;
  • Controller: The logical layer that delivers user interactions and updates to Model data;

In Android, activities/fragments are both views and controllers, resulting in heavy Activity/Fragment loads. In MVC, views interact directly with the Model, so Activity/Fragment is highly coupled to the Model.

Advantages:

  1. Coupling is reduced. MVC is essentially layered coupling, reducing the interaction between code.
  2. Good scalability, due to low coupling, when increasing requirements, small changes, small probability of bugs.

Disadvantages:

As the project grows, the Activity/Fragment code becomes bloated.

MVP

MVP is short for Model, View and Presenter. Is an evolution of the well-known MVC pattern. The MVP pattern changes the MVC Controller to Presenter and changes the direction of communication. View and Model are isolated, and Presenters are responsible for the interaction between the View layer and Model layer.

  • A View corresponds to an Activity and is responsible for drawing the View and interacting with the user
  • The Model is still the business logic and entity Model
  • Presenter is responsible for completing the interaction between View and Model

Communication between the parts is two-way.

Advantages:

  1. The Model layer can be encapsulated and reused, which can greatly reduce the amount of code.
  2. The View and Model are less coupled, making each more focused on its own business.
  3. The model is completely separate from the view, and we can modify the view without affecting the model.
  4. Models can be used more efficiently because all interaction takes place inside the Presenter.
  5. We can use one view for multiple views without changing the Presenter’s internal logic. This feature is useful because the view always changes more frequently than the model.
  6. By putting program logic in Presenter, we can test it out of the user interface. (Unit test)

Disadvantages:

As the business logic increases, a page can become very complex and the UI can change a lot. As a result, the View interface will become very large and the Presenter layer code will become more and more bloated.

Specific examples:

View interface: The View interface is the middle layer between the Activity and Presenter layer. It provides a method for the Presenter to invoke specific UI logical operations in the Activity according to the needs of the specific business.

Public interface IMvpview {/** * displays loading progress */ void showLoading(); /** * hide the loading progress box */ void hideLoading(); /** @param data source */ void showData(String data); /** @param data source */ void showData(String data); Void showFailureMessage(String MSG); void showFailureMessage(String MSG); */ void showErrorMessage(); */ void showErrorMessage(); }Copy the code

Presenter Interface: The Presenter interface is an intermediate layer between Presenter and model. It provides the Model layer with methods to call the Presenter layer.

public interface IMvpPresenter {

    void onSuccess(String data);

    void onFailure(String msg);

    void onError();

    void onComplete();
}
Copy the code

Model interface: The Model interface is used to provide methods for concrete business logic processing

Public interface IMvpModel {/** * @param data */ void getNetData(String data); }Copy the code

The Activity class

public class MainActivity extends AppCompatActivity implements IMvpview, View.OnClickListener { private MvpPresenter mvpPresenter; // Progress bar ProgressDialog; TextView text; Button btn1, btn2, btn3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView) findViewById(R.id.text); btn1 = (Button) findViewById(R.id.btn1); btn2 = (Button) findViewById(R.id.btn2); btn3 = (Button) findViewById(R.id.btn3); btn1.setOnClickListener(this); btn2.setOnClickListener(this); btn3.setOnClickListener(this); ProgressDialog = new progressDialog (this); progressDialog.setCancelable(false); ProgressDialog. SetMessage (" loading data "); mvpPresenter = new MvpPresenter(); mvpPresenter.attachView(this); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.btn1: mvpPresenter.getData("normal"); break; case R.id.btn2: mvpPresenter.getData("failure"); break; case R.id.btn3: mvpPresenter.getData("failure"); break; } } @Override public void showLoading() { if (! progressDialog.isShowing()) { progressDialog.show(); } } @Override public void hideLoading() { if (progressDialog.isShowing()) { progressDialog.dismiss(); } } @Override public void showData(String data) { text.setText(data); } @Override public void showFailureMessage(String msg) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); text.setText(msg); } @override public void showErrorMessage() {toast.maketext (this, "toast.length_short ", toast.length_short).show(); Text.settext (" network request data exception "); } @Override protected void onDestroy() { super.onDestroy(); // Disconnect the View reference from mvpPresby.detachView (); }}Copy the code

Presenter class

public class MvpPresenter implements IMvpPresenter { private IMvpview iMvpview; private MvpModel mvpModel; public void getData(String params) { iMvpview.showLoading(); mvpModel.getNetData(params); } public void attachView(IMvpview IMvpview) {this. IMvpview = IMvpview; mvpModel = new MvpModel(this); } /** * Public void detachView() {this.imvpView = null; } / / public Boolean isViewAttached() {return iMvpview! = null; } @Override public void onSuccess(String data) { if (isViewAttached()) { iMvpview.showData(data); } } @Override public void onFailure(String msg) { if (isViewAttached()) iMvpview.showFailureMessage(msg); } @Override public void onError() { if (isViewAttached()) iMvpview.showErrorMessage(); } @Override public void onComplete() { if (isViewAttached()) iMvpview.hideLoading(); }}Copy the code

Model class

public class MvpModel implements IMvpModel { private IMvpPresenter iMvpPresenter; public MvpModel(IMvpPresenter iMvpPresenter) { this.iMvpPresenter = iMvpPresenter; } @override public void getNetData(final String param) {new Handler().postdelayed (new) Runnable() { @Override public void run() { switch (param) { case "normal": Imvppresby. onSuccess(" Request network data success according to parameter "+ param + "); break; Case "failure": iMvpPresenter. OnFailure (" Request failed: parameter wrong "); break; case "error": iMvpPresenter.onError(); break; } iMvpPresenter.onComplete(); }}, 2000); }}Copy the code

1. Interfaces explode. Building a project in MVP mode results in too many class files and interface files, which increases the size of the package

Write a Contract interface and include all interfaces related to MVP in it

2, will cause the problem of memory leakage. When the user turns off the View layer and the Model layer is still doing time-consuming operations, the garbage collector can’t collect the View layer because the Presenter layer also holds references to the View layer, which causes a memory leak.

You can override onDestroy() to force the Presenter to be recycled when the View is destroyed. Or weak reference (before a reference is referenced, check that the reference is not null to prevent null pointer exceptions.)