Ali Daniel: The choice is greater than the effort, so how should I choose MVC, MVP, MVVM?

Foreword


MVC, MVP, MVVM are important parts of our job and interview, but many times we are a little confused. For example, after reading a lot of articles, I do n’t understand what MVC is. I originally wanted to write an MVP and wrote it, and it became MVC. In the end, what is the shameful relationship between Databing and MVVM. This article mainly introduces from a development perspective, such as mvp, mvvm appear to solve the former problems. If you have the same question, this article may bring you some gains. However, architecture and design patterns are not so easy to understand, many of them need to be experienced before they can be realized. In addition, due to my limited level, if you write incorrectly or rigorously, please do not hit me.

MVC


Perhaps due to the rise of MVP and MVVM, the application of MVC in android has become less and less, but MVC is the foundation, and understanding MVC can better understand MVP and MVVM. Because the latter two are developed based on MVC.

1. MVC dazzling design

When we searched for mvc related materials from the Internet, if you read a few more articles, you may find that the design drawings they introduced are not the same. Most of the design drawings are listed here

2. Explanation of MVC design drawing

Which of the design drawings listed above is correct? In fact, they are all right. Why do you say that, it has to start with the development of mvc.

The MVC framework pattern was first proposed by Trygve Reenskaug on the Smalltalk-80 system in 1978. After so many years of development, of course, different versions will evolve, but the core has not changed and is still a three-layer model Model-View-Control.

3. The relationship between the three layers of MVC

The arrow → represents a flow of events, and does not necessarily need to hold each other. For example, the flow of events in the model → view in the figure above, the view can obtain the events sent by the model through the form of registered listeners. If you want to communicate between model view controllers in the design, try to design them not to directly hold them, so that they are easy to reuse, which is also in line with the original intention of mvc design. The corresponding relationship between the three in Android is as follows:

** View layer (View) ** corresponds to the xml layout file and the dynamic view part of the java code

** Control layer (Controller) ** The control layer of Android in MVC is borne by Activity. Activity was originally mainly used as an initialization page to display data operations, but because XML view function is too weak, Activity is responsible for the view The display has to add control logic, too many functions.

** Model layer (Model) ** For the business model, the established data structure and related classes, it is mainly responsible for network requests, database processing, I / O operations.

Because there is a god object activity in android, and the xml layout function in android is too weak, so activity takes most of the work. So mvc in android is more like this form:

Because activity plays the role of controller and view, controller and view are not very well decoupled, but to a certain extent, we can still decouple.
Talk is cheap. Show me the code. So much talk, let's look at the code.

4、MVC sample

Looking at the code, the implementation of mvc in Android

The structure is very simple, here introduces the key code

public interface BaseModel {
    void onDestroy();
}

As the name implies, BaseModel is the parent class of all business logic models. The onDestroy () method here is used to synchronize with the activity or fragment life cycle and do some destruction operations in destroy.

public interface Callback1<T> {
    void onCallBack(T t);
}
public interface Callback2<T,P> {
    void onCallBack(T t,P p);
}

Callback is selected according to the number of parameters that are called back when the View or Controller calls the Model


    public void  getUserInfo(String uid,Callback1<UserInfo> callback)
    {

        UserInfo userInfo= new HttpUtil<UserInfo>().get(uid);
        callback.onCallBack(userInfo);

    }

    @Override
    public void onDestroy() {

    }

    public class UserInfo
    {
        private int age;
        private String name;

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

SampleModel是我们业务逻辑的具体实现

public class SampleActivity extends AppCompatActivity {
    private SampleModel sampleModel;
    Button button;
    EditText textView;
    TextView tvAge,tvName;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);
        sampleModel=new SampleModel();
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getUserInfo(textView.getText().toString());
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        sampleModel.onDestroy();
    }

    /**
     * 获取用户信息
     * @param uid
     */
    private void getUserInfo(String uid)
    {
        sampleModel.getUserInfo(uid, new Callback1<SampleModel.UserInfo>() {
            @Override
            public void onCallBack(SampleModel.UserInfo userInfo) {
                setDataToView(userInfo);
            }
        });
    }

    /**
     * 设置用户信息到view
     */
    private void setDataToView(SampleModel.UserInfo userInfo)
    {
        tvAge.setText(userInfo.getAge());
        tvName.setText(userInfo.getName());
    }

}

Earlier said that Activity acts as View and Controller, but we still have to distinguish which part is the operation of View and which part is the operation of Controller. We analyze the flow of events. Button click event trigger: View → Controller gets user information event trigger: Controller → Model binds user information to View: Controller → View So far MVC is finished

5. MVC summary

Here we summarize according to the sample:

  • With a certain layering, the model is completely decoupled, and the controller and view are not decoupled
  • Interaction between layers should use callbacks or message mechanisms to try to avoid holding directly
  • The controller and view cannot be completely separated in Android, but it must be clearly distinguished at the code logic level
  • Business logic is placed in the model layer, which can better reuse and modify to increase business

MVP


1. MVP description

MVP is very similar to MVC. At the beginning of the article, there are many kinds of MVC design drawings, so according to the development of MVC, we ca n’t look at MVP as MVC, because MVP is also a three-tier, the only difference is that Model and No communication between Views is done through Presenter.

When I introduced MVC earlier, I mentioned that it is a fatal flaw. In Android, due to the existence of activity (god object), it is difficult to completely decouple Controller and View, but in MVP can solve this problem. Look at the design of MVP:

In general, these two.

2、MVP Sample

Still continuing the MVC example, modify the structure to achieve through MVP, see the project code structure:

callback, the content under the http package is basically the same, mainly look at different places

public interface BasePresenter {
    void onDestroy();
}

BasePresenter is similar to BaseModel in MVC and is mainly responsible for the implementation of business logic. We did not put the business logic in the Model to implement it, of course, it is also possible to put the main business logic in the Model to implement. Google's MVP implementation is to put business logic in the presenter and weaken the Model, and we do the same here.

public interface BaseView<P extends BasePresenter> {
    void setPresenter(P presenter);
}

BaseView is the parent class of all Views, abstracting the view in Android, only the operations related to the view are completed by the baseView implementation class.

public class SampleContract {
    public static class Presenter implements BasePresenter
    {
        public void  getUserInfo(String uid,Callback1<SampleModel.UserInfo> callback)
        {
            SampleModel.UserInfo userInfo= new HttpUtil<SampleModel.UserInfo>().get(uid);
            callback.onCallBack(userInfo);
        }

        @Override
        public void onDestroy() {

        }
    }
    public interface View extends BaseView<Presenter>
    {
         void setDataToView(SampleModel.UserInfo userInfo);
    }
}

Contract contract class This is another difference between Google MVP and other implementations. The contract class is used to define the view interface and presenter specific implementation of the same interface. The advantage is that the logic of the entire page can be clearly seen through the standardized method of naming and commenting.

public class SampleActivity extends AppCompatActivity implements SampleContract.View{
    private  SampleContract.Presenter mPresenter;
    Button button;
    EditText textView;
    TextView tvAge,tvName;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);
        setPresenter(new SampleContract.Presenter());

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mPresenter.getUserInfo(textView.getText().toString(), new Callback1<SampleModel.UserInfo>() {
                    @Override
                    public void onCallBack(SampleModel.UserInfo userInfo) {
                        setDataToView(userInfo);
                    }
                });
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mPresenter.onDestroy();
    }

    @Override
    public void setDataToView(SampleModel.UserInfo userInfo) {
        tvAge.setText(userInfo.getAge());
        tvName.setText(userInfo.getName());
    }


    @Override
    public void setPresenter(SampleContract.Presenter presenter) {
        mPresenter=presenter;
    }
}

The SampleActivity here implements SampleContract.View only exists as a View. Although it looks very similar to the implementation in MVC, there are essential differences. mPresenter is the bridge between Model and View. Presenter and View hold each other, here SampleActivity implements SampleContract.View, mPresenter as a member variable of SampleActivity, of course SampleActivity holds mPresenter, because mPresenter is a non-static member scalar, so it holds the reference of SampleActivity by default.

3. MVP summary

By introducing the interface BaseView, the corresponding view components such as Activity and Fragment are used to realize BaseView, which realizes the independence of the view layer, and the complete decoupling of Model and View through the middle layer Presenter. MVP completely solves the problem that the View and Controller in MVC are silly and unclear, but as the business logic increases, a page may be very complicated, the UI changes are very many, and there will be many cases, which will cause The interface of View will be huge.

MVVM


1. Description of MVVM

In MVP, we said that with the increase of business logic, when there are many changes in UI, there will be many cases related to UI, which will cause the interface of View to be huge. The MVVM solves this problem. Through a two-way binding mechanism, the data and UI content are implemented. As long as you want to change one side, the other side can update the design concept in time, which saves a lot of writing in the View layer. In many cases, only the data needs to be changed. First look at the MVVM design drawing:

Under normal circumstances, these two situations seem to be no different from MVP. In fact, the difference is still quite big. In MVP, View and presenter must hold each other to facilitate calling each other. In MVP, View and ViewModel pass Binding. For association, their previous association processing is done through DataBinding.

2. The relationship between MVVM and DataBinding

In a word, MVVM is an idea, and DataBinding is a tool that Google introduced to facilitate MVVM. Before Google launched DataBinding, because xml layout function is weak, it is very difficult to realize MVVM. The emergence of DataBinding allows us to easily implement MVVM.

3. Introduction to DataBinding

DataBinding is a tool for implementing two-way binding of views and data. Here is a brief introduction to the basic usage. For detailed usage, please refer to the official: https://developer.android.com/topic/libraries/data-binding/Enable DataBinding, only need to be in gradle Add the following code to the file:

android {    
    dataBinding{
        enabled true
    }
}

A subclass of ViewDataBinding can be dynamically generated through DataBindingUtil. The class name is composed of the layout file name capitalized with Binding, such as:

ActivitySampleMvvmBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_sample_mvvm);

We need to configure in the layout. The entity object bound to each control is wrapped with a layout. The variable name and type are configured in the data and referenced by @ {} or @ = {}, where @ = {} means Two-way binding. The controls that currently support two-way binding are as follows:

AbsListView android:selectedItemPosition
CalendarView android:date
CompoundButton android:checked
DatePicker android:year, android:month, android:day
NumberPicker android:value
RadioGroup android:checkedButton
RatingBar android:rating
SeekBar android:progress
TabHost android:currentTab
TextView android:text
TimePicker android:hour, android:minute

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data >
        <variable
            name="user"
            type="com.androfarmer.mvvm.model.SampleModel.UserInfo">
        </variable>
    </data>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@={user.name}"
        />
    <TextView
        android:id="@+id/tv_age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@={user.age+``}"
        />

</LinearLayout>
</layout>

The above is the specific usage display in xml

public static class UserInfo  extends BaseObservable
    {
        private int age;
        private String name;

        @Bindable
        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
            notifyPropertyChanged(BR.age);
        }

        @Bindable
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
            notifyPropertyChanged(BR.name);
        }
    }

In order to achieve two-way binding, you need to process the data entity class, inherit BaseObservable, and do @Bindable and notifyPropertyChanged processing on the read and write methods. You can also directly use the official ObservableField provided by the official, such as:
private ObservableField name = new ObservableField <> ()

4、MVVM Sample

In MVVM, as in MVP, the three layers are clearly divided. Activity and xml layout act as View, and ViewModel handles business logic and data acquisition, weakening Model. A lot of code is similar to the previous, only the core code, ViewModel layer is listed here:

private SampleViewModel mSampleViewModel;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivitySampleMvvmBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_sample_mvvm);
        mSampleViewModel=new SampleViewModel(binding);
        setDataToView();
    }
    private void setDataToView()
    {
        mSampleViewModel.getUserInfo("uid", new Callback1<SampleModel.UserInfo>() {
            @Override
            public void onCallBack(SampleModel.UserInfo userInfo) {
                mSampleViewModel.mViewDataBinding.setUser(userInfo);
            }
        });
    }

The xml layout code was given when the usage of databing was introduced above. Through the above code, we bind the data UserInfo to the View. For example, if we update the user information, we can directly modify the properties on the View: mSampleViewModel.mViewDataBinding.tvName.setText ("rose"); we can also modify the field information of the UserInfo entity class: mSampleViewModel.mViewDataBinding.setUser (userInfo);

From now on, bid farewell to the problems of many interfaces in the View layer in MVP, making View more concise. Modifying either side will keep the data synchronized.

5. MVVM summary

It seems that MVVM solves the shortcomings of MVC and MVP well, but due to the two-way binding of data and views, it is not easy to locate the source when there is a problem, it may be caused by data problems, or it may be the modification of view attributes in the business logic resulting in. If you plan to use MVVM in the project, you can consider using the official architectural components ViewModel, LiveData, DataBinding to implement MVVM

Discussion on how to choose MVC, MVP, MVVM


When I introduced MVC, MVP, MVVM, I did not list their advantages and disadvantages in detail. There are two main reasons:

  1. There are still a lot of conclusions on the Internet
  2. In fact, regarding the architecture, design, modularity, etc., their advantages and disadvantages are not absolute, mainly depends on how the implementer does

For example, in mvp, we have to implement a lot of specific implementations of Present and View based on business logic and page logic. If these cases are too many, it will lead to poor readability of the code. But by introducing the contract contract class, the business logic will become much clearer. So no matter which design pattern is used, as long as it is used properly, you can achieve the desired results.

If you have to say how to choose, my shallow knowledge suggests the following:

  1. If the project is simple, there is no complexity, and the future changes are not large, then do not use design patterns or architectural methods, just encapsulate each module for easy invocation, and do not use it for the purpose of using design patterns or architectural methods.
  2. For the display-oriented app, most of the business logic is on the back end. The main function of the app is to display data, interaction, etc. It is recommended to use mvvm.
  3. For tools or need to write a lot of business logic apps, use mvp or mvvm.
  4. If you want to learn the architecture and design patterns through a project, it is recommended to use MVC and then slowly tap and improve on this basis. In the end you may find that the final result of the improvement may become mvp, mvvm.

PS: Many parts of the code are just for demonstrating the principles of specific design patterns, some are pseudo-code, and some codes are not so rigorous.

The reference for this article is as follows: http://www.voidcn.com/article/p-ssodjasa-brk.htmlhttps://www.jianshu.com/p/4830912f5162

Author: Ren Yugang

Published 34 original articles · Like1 · Visits 756

Guess you like

Origin blog.csdn.net/Android725/article/details/105499296
Recommended