This article is sponsored by Yugangshuo writing platform

By AndroFarmer

Copyright: this article belongs to the wechat public account Yu Gang said all, without permission, shall not be reproduced in any form

preface

MVC, MVP, AND MVVM are important parts of our jobs and interviews, but a lot of times we get confused. For example, I read a lot of articles and I don’t know what MVC is. I wanted to write an MVP but it turned into AN MVC. What is the relationship between Databing and MVVM? This article will focus on the development aspects, such as MVP, and what problems MVVM was created to solve. If you have the same question, this article may give you a little insight. But the architecture and the design pattern is not so easy to understand the things, many need to be experienced in practice, and because of my limited level, if the wrong or not rigorous place, 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, a good understanding of MVC to better understand MVP,MVVM. Because the latter two are based on MVC.

1, MVC dazzling design

When we look at MVC on the Internet, if you read a couple of articles, it seems like they’re all different, but most of them are listed here

2. Interpretation of MVC design drawings

Which of the plans listed above is correct? It’s all true. Why? Well, it all started with the evolution of MVC. The MVC framework pattern was first proposed in 1978 by Trygve Reenskaug on the Smalltalk-80 system. Over the years, of course, different versions have evolved, but the core remains the same: the three-tier Model, Model-View-Control.

3. The relationship between the three layers of MVC

The arrow → represents an event flow and does not necessarily hold each other. For example, the event flow from Model → View in the figure above can be obtained by the view by registering the listener. When model View controllers communicate with each other in the design, they should be designed not to be directly held in order to facilitate reuse. It is also in line with the design intention of MVC. In Android, the corresponding relationship among the three is as follows:

The View layer corresponds to the XML layout file and the Dynamic View section of Java code

The control layer of Android in MVC is assumed by the Activity. The Activity is mainly used to initialize the page and display the operation of data, but because the XML view function is too weak, so the Activity is responsible for the display of view and add control logic. Taking on too many functions.

Model layer (Model) for business Model, established data structure and related classes, it is mainly responsible for network request, database processing, I/O operation.

Because of the existence of a God Object activity in Android, and the weak functionality of the XML layout in Android, the activity does most of the work. So MVC in Android looks more like this:

4, the MVC sample

Let’s look at the implementation of MVC in Android through the code

The structure is simple, but here’s the key code

public interface BaseModel {
    void onDestroy();
}
Copy the code

BaseModel is the parent class of all business logic models. The onDestroy() method is used to synchronize with the activity or fragment lifecycle to do some destruction in destroy

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

Callback is used based on the number of parameters that the View or Controller calls the Model

public class SampleModel  implements BaseModel{

    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; }}}Copy the code

SampleModel is a concrete implementation of our business logic

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 voidonDestroy() { super.onDestroy(); sampleModel.onDestroy(); } /** * Obtain user information * @param uid */ private void getUserInfo(String uid) {samplemodel.getUserInfo (uid), new Callback1<SampleModel.UserInfo>() { @Override public void onCallBack(SampleModel.UserInfo userInfo) {setDataToView(userInfo); }}); } /** * Set user information to view */ private voidsetDataToView(SampleModel.UserInfo userInfo) { tvAge.setText(userInfo.getAge()); tvName.setText(userInfo.getName()); }}Copy the code

We said that the Activity acts as a View and a Controller, but we still need to distinguish between which part of the Activity is a View operation and which part is a Controller operation. Button click event trigger: View→Controller Get user information event trigger: Controller→Model Bind user information to View: Controller→View

5. MVC summary

Here we summarize according to sample:

  • With a certain level of stratification, the model is completely decoupled, but the controller and view are not decoupled
  • Interactions between layers should be done using callbacks or messaging mechanisms, avoiding direct holding
  • Controllers and views cannot be completely separated on Android, but they must be separated at the logical level of the code
  • The business logic is placed in the Model layer for better reuse and modification to add business

MVP

1. MVP description

MVP is very similar to MVC. In terms of the development of MVC, we can consider MVP as MVC, because IT has three layers. The only difference is that there is no communication between Model and View, and it is done by Presenter. As mentioned in the previous introduction of MVC, it is a fatal shortcoming. In Android, due to the existence of Activity (God Object), Controller and View are difficult to achieve complete decoupling. But the MVP is a great way to solve this problem. Look at the MVP design:

2, the MVP of the Sample

Continue with the MVC example, and change the structure to implement by MVP. Look at the project code structure:

public interface BasePresenter {
    void onDestroy();
}
Copy the code

BasePresenter is similar to BaseModel in MVC. It is mainly responsible for the implementation of business logic. We have not implemented the business logic in the Model, of course it is possible to implement the main business logic in the Model. Google’s MVP implementation is to put the business logic in a presenter and weaken the Model, which is what we do here.

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

BaseView is the parent class of all views, which abstracts the View in Android. Only the BaseView implementation class does all the operations related to the View.

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); }}Copy the code

Another difference between Google MVP and other implementations is that the Contract class is used to define the interface of a View and the concrete implementation of a Presenter in the same interface. The advantage is that you can clearly see the logic of the entire page through the naming and annotation of the canonical method.

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 voidonDestroy() {
        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; }}Copy the code

Here the SampleActivity implements samplecontract. View only exists as a View. Although it looks very similar to the implementation in MVC, there are essential differences. MPresenter is a bridge between Model and View. In this case, SampleActivity implements samplecontract.view. The mPresenter is a member variable of SampleActivity, and of course SampleActivity owns the mPresenter. Because the mPresenter is a non-static member scalar, it holds a reference to the SampleActivity by default.

3. MVP summary

Through the introduction of interface BaseView, let the corresponding View components such as Activity, Fragment to realize BaseView, realize the independence of View layer, through the middle layer Preseter to realize the complete decoupling of Model and View. MVP completely solved the problem of View and Controller in MVC, but with the increase of business logic, a page may be very complex, UI changes are very many, there will be a lot of cases, so that the View interface will be very large.

MVVM

1. MVVM description

In MVP we said that as business logic is added and the UI changes a lot, there will be a lot of UI-related cases, which will cause the View interface to be very large. MVVM solves this problem by bidirectional binding mechanism to realize data and UI content. As long as you want to change one side, the other side can be updated in time. This eliminates the need to write many cases in the View layer and only needs to change the data. Take a look at the MVVM design:

2. Relationship between MVVM and DataBinding

In short, MVVM is an idea, and DataBinding is Google’s tool for making it easy to implement MVVM. Before Google launched DataBinding, it was difficult to implement MVVM because XML layout was weak. The advent of DataBinding makes it easy to implement MVVM.

3. Introduction to DataBinding

DataBinding is a tool that implements two-way binding between views and data. Here is a brief introduction to the basic usage of DataBinding. Detailed usage may follow the official: https://developer.android.com/topic/libraries/data-binding/ DataBinding, need only in gradle file add the following code:

android {    
    dataBinding{
        enabled true}}Copy the code

Create a ViewDataBinding subclass using DataBindingUtil. Create a ViewDataBinding subclass using a layout file uppercase and Binding.

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

In layout, we need to configure the entity object bound to each control to wrap it with layout. In data, we need to configure variable names and types, which are referenced by @{} or @={}, where @={} means two-way binding. Currently, the following controls support bidirectional binding:

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>

Copy the code

The above shows the specific use of 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); }}Copy the code

In order to implement bidirectional binding, we also need to handle the data entity class, inherit BaseObservable, and do @bindable and notifyPropertyChanged for the read and write methods. Private ObservableField name=new ObservableField<>(); private ObservableField name=new ObservableField<>();

4, MVVM Sample

In MVVM, just like in MVP, the three layers are clearly divided. Activity and XML layout act as View. ViewModel processes business logic and obtains data, weakening Model. Much of the code is similar, but only the core code, the ViewModel layer, is listed

public interface BaseViewModel {
    void onDestroy();
}

public abstract class AbstractViewModel<T extends ViewDataBinding> implements BaseViewModel {
    public T mViewDataBinding;
    public AbstractViewModel(T viewDataBinding)
    {
        this.mViewDataBinding=viewDataBinding;
    }

    @Override
    public void onDestroy() { mViewDataBinding.unbind(); } } public class SampleViewModel extends AbstractViewModel<ActivitySampleMvvmBinding> { public SampleViewModel(ActivitySampleMvvmBinding viewDataBinding) { super(viewDataBinding); } public void getUserInfo(String uid, Callback1< samplemodel.userinfo > callback) {// get information from the network or cache samplemodel.userInfo UserInfo =new Samplemodel.userinfo (); userInfo.setName("tom"); userInfo.setAge(18); callback.onCallBack(userInfo); }}Copy the code

The ViewMode layer deals with business logic and data, and mViewDataBinding is passed through the View layer.

 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); }}); }Copy the code

The XML layout code that binds the UserInfo data to the View is shown in the above section of databing. For example, we update user information, can be directly to View the properties of the modified: mSampleViewModel. MViewDataBinding. TvName. SetText (” rose “); Can also by modifying the UserInfo entity class field information: mSampleViewModel. MViewDataBinding. SetUser (the UserInfo);

Let’s get rid of the many interface problems in the View layer in MVP, and make the View more concise. Modify either side, and both will keep data synchronized.

5. MVVM summary

MVVM seems to be a good solution to the shortcomings of MVC and MVP, but due to the two-way binding between data and view, it is difficult to locate the source of problems, which may be caused by data problems, or by changes to view properties in business logic. If you plan to use MVVM in your project, consider using the official architecture components ViewModel, LiveData, and DataBinding to implement MVVM

How to choose MVC,MVP and MVVM

There are two main reasons why MVC, MVP, and MVVM were not mentioned in detail:

  1. This aspect is summed up on the net still quite much
  2. In fact, about the architecture, design, modularity and so on, their advantages and disadvantages are not absolute, mainly depends on the implementer how to do

For example, in MVP we have to implement a lot of Present and View implementations based on business logic and page logic. If there are too many cases, the code will become less readable. But by introducing the Contract contract class, the business logic becomes much clearer. Therefore, no matter what kind of design pattern, as long as the use of proper, can achieve the desired results. If I had to say how to choose, my shallow knowledge would suggest the following:

  1. If the project is simple, there is no complexity, and the future changes are not significant, then don’t use the design pattern or architectural approach, just encapsulate each module and make it easy to call, don’t use the design pattern or architectural approach just for the sake of using it.
  2. For apps with a bias towards presentation, most of the business logic is in the back end, and the main functions of apps are data display and interaction, etc. MVVM is recommended.
  3. For utility classes or apps that need to write a lot of business logic, use EITHER MVP or MVVM.
  4. If you want to learn architecture and design patterns through a project, it is recommended that you use MVC and then slowly build on it. In the end, you may find that the end result of the improvement may become MVP, MVVM.

PS: Much of the code is just to demonstrate the principles of specific design patterns, some of it is pseudocode, and some of it is not so rigorous. This article is referred to as follows:

http://www.voidcn.com/article/p-ssodjasa-brk.html https://www.jianshu.com/p/4830912f5162

Welcome to follow my wechat official account to receive first-hand technical dry goods