Why do architecture design? As an APP grows bigger and bigger, with more and more complex business and requirements, architecture needs to be considered in order to improve the scalability of the system. Of course, small companies in the basic will not involve these, one is because the project is relatively small, mainly to complete the function, and the demand is not much, need to modify the place is not much; The other is that there’s a good chance you’re done with the project and you’re done with it, and you don’t even have to think about future expansions. Therefore, knowledge such as architecture design, performance optimization, NDK (Java can’t solve, low efficiency, poor security), RN (performance can be updated) is a must for us to get to the big company or to play in the big company. We need to constantly expand our programming horizons, not say nothing, no matter how talented we are. In addition, we also need to study at the bottom, otherwise it is easy to be eliminated.

When we talk about MVP, we will talk about MVC. MVC was invented to solve interface programming such as Android development. As the functionality and requirements of the application continue to increase, it is important to keep the architecture clear and extensible. MVC was first proposed by Microsoft, so I put out the following diagram:

In MVC: Model and View represent business logic and presentation mode. Model and View often refer to each other. When changing presentation mode, it is likely to modify the business logic layer, that is, to modify Controller.

So in order to get rid of that, we need to decouple, and we have MVP, and MVVM and so on, which is beyond our scope.

In MVP, let’s take a look at the three concepts first: Model: business logic, job description: load data. View: A View whose job description is to control how data is displayed. Presenter: An intermediary, bound to a Model or View.

###### Note: In Android, an Activity is often thought of as a View implementation class.

The MVP architecture diagram looks like this:

While the MVP is a bit more cumbersome to use, its advantages are obvious: The Model and View are sufficiently decoupled that modifying one does not involve the other. In addition, views and business logic can also change, so views and business logic can be extracted into interfaces and different implementation classes can be changed. Presenter holds only Model and VIew references and can change their implementation classes at any time, making the implementation open to extension. Therefore, COMPARED with MVC, MVP has clearer specifications and stronger expansibility in system architecture.

# # # chestnuts

All right, so much for that, but it doesn’t help, right? It doesn’t matter, we show chestnuts, on the code ha!

Let’s take a look at the project architecture of our entire demo. Let’s call this demo # 1.

Let’s introduce it step by step.

1. As an APP, the display of the interface needs data, so we need data first. Let’s create a package for the Model, and so on. Because in MVP, our data and display are implemented through interfaces, we need to create an interface: iMainModel.java, preceded by a capital I for the interface type. public interface IMainModel {

void loadData(OnLoadCompleteListener listener); interface OnLoadCompleteListener { void onComplete(String data); }}Copy the code

The IMainModel interface is responsible for loading the data and calling back when the load is complete.

2. Then we need to implement the IMainModel interface. We will do the first version and load data locally.

public class MainModelImpl implements IMainModel { @Override public void loadData(OnLoadCompleteListener listener) { String data = "I'm loading data locally "; listener.onComplete(data); }}Copy the code

3, then we need the View interface, here we define two relatively simple methods, one is to load the data when the progress bar, and then is to display the loaded data.

		public interface IMainView {

		    void showLoading();
		    void showData(String data);

		}
Copy the code

4. As mentioned in the above concept, our Activity is a View implementation class, so the Activity needs to implement the View interface, and implement the abstract method of the View interface. In this case, for simplicity, let’s assume that our data is loaded from the network in the Model. When loading is in progress, we display a Toast, and when loading is successful, we display the data on the TextView.

public class MainActivity extends AppCompatActivity implements IMainView { private MainPresenter mPresenter; private TextView tv_test; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_test = (TextView) findViewById(R.id.tv_test); } @override public void showLoading() {toast.maketext (this, "... , Toast.LENGTH_SHORT).show(); } @Override public void showData(String data) { tv_test.setText(data); }}Copy the code

5. After going through the above process, we need to have an intermediary that binds the View (Activity) to our Model, as shown below. Presenter is a class that needs to hold an interface to the View and Model, rather than an implementation. Initializes the Model object during Presenter construction and receives the View object (Activity). Finally, a fetch method is provided to bind the two and perform the specific business logic, which will not be covered here.

public class MainPresenter { private IMainModel mModel; private IMainView mView; public MainPresenter(IMainView view) { mModel = new MainModelImpl(); mView = view; } public void fetch() { mView.showLoading(); mModel.loadData(new IMainModel.OnLoadCompleteListener() { @Override public void onComplete(String data) { mView.showData(data); }}); }}Copy the code

6. Finally, instantiate our Presenter object in the Activity’s onCreate method.

public class MainActivity extends AppCompatActivity implements IMainView { private MainPresenter mPresenter; private TextView tv_test; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_test = (TextView) findViewById(R.id.tv_test); // Instantiate Presenter mPresenter = new MainPresenter(this); mPresenter.fetch(); } @override public void showLoading() {toast.maketext (this, "... , Toast.LENGTH_SHORT).show(); } @Override public void showData(String data) { tv_test.setText(data); }}Copy the code

Take a look at the effect of chestnut # 1:

### THE role of MVP in system expansion

The above is just a basic introduction to the use of MVP. The following are the most awesome aspects of using MVP in a project. As we continue to grow, iteration, development and expansion, our project team put forward new requirements.

##### Requirement 1: Our data can no longer be loaded locally and needs to be loaded via the network instead. Taking a look at the MVP architecture, our logic for loading data is implemented through Model implementation classes, so this requirement can be implemented directly by replacing different Model implementation classes. This is the object oriented OCP principle, which is that the program is closed for modification and open for extension. All right, without further ado, it’s time to operate on Chestnut One.

According to our analysis, we can directly create a new Model implementation class named MainModeNetlImpl and modify the business logic of loadData to loadData from the network. In real projects, it can be very complex code, so here is a simple explanation to illustrate the advantages of MVP. If there is no MVP or MVC architecture in the project, it will be difficult to modify it. MVP (MVC) layering makes the overall architecture of the project clearer.

public class MainModeNetImpl implements IMainModel { @Override public void loadData(OnLoadCompleteListener listener) { String data = "I loaded data from the network "; listener.onComplete(data); }}Copy the code

Then replace our Model implementation class in our Presenter, as shown below.

public class MainPresenter { private IMainModel mModel; private IMainView mView; public MainPresenter(IMainView view) { // mModel = new MainModelImpl(); mModel = new MainModeNetlImpl(); mView = view; } public void fetch() { mView.showLoading(); mModel.loadData(new IMainModel.OnLoadCompleteListener() { @Override public void onComplete(String data) { mView.showData(data); }}); }}Copy the code

Then this is chestnut number two after the transformation:

###### extension: Of course, if your project manager brain brain, change, sometimes from the network load, sometimes feel bad and local load; Or the application may need to load data from different places in different situations. Here we can use the policy pattern to load data from different places depending on the situation. So we can do the following in Presenter:

	    public MainPresenter(IMainView view, boolean isFromNet) {
		if (isFromNet) {
		    mModel = new MainModeNetImpl();
		} else {
		    mModel = new MainModelImpl();
		}
		mView = view;
	    }
Copy the code

Well, maybe after a few days the project manager has a fit (SHH, don’t say it too loudly) and needs to change it again!

##### Requirement 2: Our data display method needs to be changed, for example, to display data to different controls, etc., so we can directly create a different Activity, implement the View interface, make the corresponding modification, here no further details.

# # # MVP to improve

There are some problems with using MVP above:

##### Q1: newPresenter has to be manually used every time. There is a lot of repetitive code. Can we extract the base class MVPBaseActivity to simplify our code? ##### Q.2: Does the above writing create memory leaks?

Our View (Activity) holds a reference to the Presenter, which in turn holds a reference to the Model. This creates a chain of references, as shown in the following figure:

Our Model can be very time consuming to load data, and once the Activity is destroyed during loading, it can cause a memory leak. For example, when loading data, the user presses the return key to destroy the Activity, but because of the above reference chain, the Activity cannot be recycled normally.

In order to simulate this phenomenon, we delay the Model data by 5 seconds through Handler, and rotate the screen during the loading process to make the Activity rebuild, as shown in the code below:

public class MainModeNetImpl implements IMainModel { private Handler mHandler = new Handler(); @Override public void loadData(final OnLoadCompleteListener listener) { mHandler.postDelayed(new Runnable() { @Override Public void run() {String data = "I loaded data from network "; listener.onComplete(data); }}, 5000); }}Copy the code

When the screen is rotated during loading, the Activity is rebuilt, and the Memory Monitor of Android Studio dumps the Memory information, we can see that the Activity cannot be reclaimed properly. There are two mainActivities in Memory, as shown in the following figure:

##### Solution

High energy ahead, please fasten your seat belt, brother, steady!

To address memory leaks, we create Presenter at Activity creation time and unbind it at destruction time.

public abstract class MVPBaseActivity<V, P extends BasePresenter<V>> extends AppCompatActivity { protected P mPresenter;  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // createPresenter mPresenter = createPresenter(); AttachView ((V) this); } @Override protected void onDestroy() { super.onDestroy(); mPresenter.detachView(); } protected abstract P createPresenter(); }Copy the code

The BasePresenter code is as follows:

		public abstract class BasePresenter<V> {

		    protected WeakReference<V> mViewRef;

		    public void attachView(V view) {
			mViewRef = new WeakReference<>(view);
		    }

		    public void detachView() {
			if (mViewRef != null) {
			    mViewRef.clear();
			    mViewRef = null;
			}
		    }

		    protected V getView() {
			return mViewRef.get();
		    }

		}
Copy the code

Through the above base class extraction to achieve class Model and View binding and unbinding, that is, to achieve the association of the life cycle of the two. In addition, when the memory is insufficient, the Model should be eliminated first, and then the View should be eliminated to give the user a good experience effect.

This is the MVP architecture and extension we are going to talk about today. In the process, we have not only mastered the MVP architecture, but also consolidated the object-oriented OCP principles, the strategy pattern in the design pattern, memory leakage related knowledge and so on. Therefore, knowledge is a whole system, interrelated, existence must exist meaning.

In addition, I drew a picture when writing blog, in the interview we may often be asked: source code, principle, mechanical things, at this time we should draw a picture of the time to draw a picture, the metaphor of the metaphor, draw for the interviewer, the interviewer will feel refreshed.

If you feel that my words are helpful to you, welcome to pay attention to my public number:

My group welcomes everyone to come in and discuss all kinds of technical and non-technical topics. If you are interested, please add my wechat huannan88 and I will take you into our group.