1. Advantages and disadvantages of MVP mode

Before we get to MVVM, let’s briefly review the MVP hierarchy, which is divided into three tiers:

  • A, View: View layer, corresponding to XML file and Activity/Fragment;
  • B. Presenter: a logic control layer that holds both View and Model objects.
  • C. Model: entity layer, responsible for obtaining entity data.
MVP mode sequence diagram

The MVP model has great advantages

  • 1. Decoupling, separating business logic from view;
  • 2. The code structure of the project (folder) is clear, and you can see what classes do what things;
  • 3. Easy unit testing (actually number one);
  • 4. Collaborative work (for example, the designer can write some business logic code before drawing or it is easier for others to take over the code and change it);

But there are also some fly in the ointment. The MVP model has the following drawbacks:

  • 1.Presente layer interacts with View layer through interface, and interface granularity is not easy to control. If the granularity is too small, there will be a large number of interfaces, making the code too fragmented; Too large particle size, poor decoupling effect. For example, if a View defines a method for a Presenter, it is not necessary to delete it. For example, if a View defines a method for a Presenter, it is not necessary to delete it.
  • 2.V layer and P layer still have a certain degree of coupling. Whenever a UI element changes at the V layer, the interface must be changed, how the data is mapped to the UI, the event listener interface, and so on. It would be nice if this layer could also be decoupled.

  • 3. Complex business may also lead to too large P layer, and the problem of bloated code is still unsolved, which is no longer a problem of interface granularity control. Once there are more and more business logic and more and more methods defined by views, it will result in more and more methods implemented by activities and fragments, which are still bloated.

### MVVM mode

####2.1, two-way data binding OK, now to introduce MVVM, MVVM mode is not four layers, the same as MVP is three layers, but I do not agree that MVVM is an upgrade version of MVP, the two have the same place, but some of the advantages of MVP, MVVM can not replace, MVVM three-layer model is as follows:

Model: Responsible for data implementation and logic processing, similar to MVP. View: Corresponding to Activity and XML, responsible for drawing views and interacting with users, similar to MVP. ViewModel: Creates an association that binds the Model to the view. After that, changes to our Model are fed back to the View via the ViewModel. (View XML layout file, after special preparation, compilation tool processing, generated code will receive viewModel data notification message, automatic refresh interface).

As you can see, the biggest highlight of the MVVM pattern is bidirectional binding

With unidirectional binding, the flow of data is unilateral and can only flow from code to THE UI. The data flow of bi-directional binding is bi-directional, and the data on the UI can be refreshed as the data in the business code changes; As the user interacts with the UI to edit the data, the changes to the data are automatically updated to the data in the business code. For bidirectional binding, you can just use DataBinding, a framework for data and UI binding that is a key tool for building MVVM patterns. So it’s much easier to implement MVVM on Android, use block callbacks on IOS, or use the reactiveCocoa library.

####2.2 basic usage of DataBinding

# # # # # – Gradle configuration

Just turn on dataBinding in the Android domain of Gradle.

#####- Create entity classes

public class User {
    private String name;
    private String age;

    public void onItemClick(View pView) {
        Toast.makeText(pView.getContext(), getName(), Toast.LENGTH_SHORT).show();
    }

    public String getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    public User(String name, String age) {
        this.name = name;
        this.age = age; }}Copy the code

When binding is implemented, layout authoring differs from traditional XML

activity_main.xml <? xml version="1.0" encoding="utf-8"? > <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="user" type="mvvm.wangjing.com.mvvm.User.User" /> </data> <RelativeLayout android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="mvvm.wangjing.com.mvvm.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:onClick="@{user.onItemClick}" android:text="@{`My name is `+ user.name+` I'm `+user.age+` years old `}" /> </RelativeLayout> </layout>Copy the code

With DataBinding, a layout with a tag as its root node will eventually generate aBinding class named capitalize the word, remove the underscore, and add aBinding at the end. I have activity_main.xml here, so an ActivityMainBinding is generated.

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        ActivityMainBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        User user = new User("Looperjing"."20"); viewDataBinding.setUser(user); }}Copy the code

Put the setContentView (R.l ayout. Activity_main) into DataBindingUtil. The setContentView (this, R.l ayout. Activity_main), The generated binding class ActivityMainBinding is returned, and user is then bound. The result is as follows.



public class User extends BaseObservable {

    public ObservableField<String> name = new ObservableField<>();

    public ObservableField<String> age = new ObservableField<>();


    public User(String pName, String pAge) {
        name.set(pName);
        age.set(pAge);
    }

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

    public void setName(String name) {
        this.name.set(name);
        notifyPropertyChanged(mvvm.wangjing.com.mvvm.BR.name);
    }

    @Bindable
    public String getAge() {
        return age.get();
    }

    public void setAge(String age) {
        this.age.set(age);
    }

    public void onItemClick(View pView) {
        Toast.makeText(pView.getContext(), name.get(), Toast.LENGTH_SHORT).show();
        setName("June"); }}Copy the code

Public ObservableField Name = New ObservableField<>() is used to create the property. The ObservableField is used to automatically notify the View to refresh when the value in our entity class changes. Name.get () is used to get the property value, and name.set() is used to set the property value. If you want to change a field, it is necessary to the field of the get method add @ Bindable annotations, and then give the field set method combined with notifyPropertyChanged (mvvm.wangjing.com.mvvm.BR.name), The above code shows how to change the value of name when clicking View. For a more advanced use of dadabinding, see: Poke me.

For ObservableField these fields can be sorted and wrapped up a little bit. For example, some fields are bound to some Style properties of the control (such as length, color, size). For such fields, you can declare a ViewStyle class to wrap them, so that the whole code logic is clearer, otherwise it is not easy to read. For other fields, such as title, imageUrl and name, which belong to the data source type, these fields are also called data fields and are closely related to business data and logic, these fields can be put together.

The above demonstration of how DataBinding is bidirectionally bound is a key part of the ViewModel that implements the MVVM pattern.

2.2. MVVM mode in Android

####a, View layer The View layer is XML and Activity

<? xml version="1.0" encoding="utf-8"? > <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="model" type="mvvm.wangjing.com.mvvm.User.UserViewModel" /> </data> <RelativeLayout android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="mvvm.wangjing.com.mvvm.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:onClick="@{model.onItemClick}" android:text="@{`My name is `+ model.user.name+` I'm `+model.user.age+` years old `}" /> </RelativeLayout> </layout>Copy the code

Note that the UserViewModel is imported this time, which is the VM layer of the MVVM. When the Model business data changes, it notifies the Model of UI updates, and when the UI updates, it notifies the Model of changes.

  <data>
        <variable
            name="model"
            type="mvvm.wangjing.com.mvvm.User.UserViewModel" />
    </data>Copy the code
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final ActivityMainBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        UserViewModel userViewModel=new UserViewModel(this,viewDataBinding); }}Copy the code

It can be found that the View layer does uI-related work. We only write the View layer code in XML, Activity and Fragment. The View layer does not do business related things, that is, we do not write business logic and business data related code in the Activity. Try to do it inside the ViewModel.

# # # #, the ViewModel layer b


public class UserViewModel {

    // Note that this field must be defined as public otherwise it cannot be read

    public User user;

    public ActivityMainBinding mainBinding;

    public Activity activity;


    public UserViewModel(Activity pActivity, ActivityMainBinding pMainBinding) {
        this.activity = pActivity;
        this.mainBinding = pMainBinding;
        mainBinding.setModel(this);
        init();
    }

    private void init() {
       user=new User("LooperJing"."20");
    }

    public void onItemClick(View pView) {
        Toast.makeText(pView.getContext(), "Notify the Medel layer, request asynchronously, get user information.", Toast.LENGTH_SHORT).show(); }}Copy the code

The ViewModel layer does not hold references to any controls, nor does it update the UI through references to UI controls in the ViewModel. But the ViewModel may change the data, and since the data is already bound to the UI, the corresponding control will automatically update the UI.

C # # # #, the Model layer

The Model layer is responsible for data acquisition, and the network request logic is written in it, similar to MVP. So I think the ViewModel layer could hold a reference to the Model, tell the Model to get the data, and then the Model, when it gets the data, call back to tell the ViewModel to make the data change, and then update the UI.

To sum up: The Activity in the View layer generates aBinding instance from the DataBinding and passes the instance to the ViewModel. The ViewModel layer binds itself to the Binding instance and implements a bidirectional Binding between a View and a ViewModel. If the ViewModel layer is not introduced, there is another disadvantage: An XML file may involve multiple data objects, so we have to introduce the multiple data objects, the clarity of THE XML layout is reduced. Through this method, we only need to introduce the ViewModel into the data tag of the layout file. All other data objects are handled together in the ViewModel. The collaboration among the three can be shown as follows:

from Kelin

####d, MVVM problem Number one: data binding makes bugs hard to debug. If you see an exception in the interface, you may have a Bug in your View code or a problem in your Model code. Data binding allows bugs in one location to be quickly transferred to another location, making it difficult to locate the original problem. Second point: For large projects, data binding requires more memory. As for the understanding of MVVM, I found that on the network, everyone has the same understanding on the whole, but there are some differences in details, for example, the division of business logic of MVVM is not very clear, some people will write in ViewModel, some will write in Moldel, and even some opponents poke me. I think that MVVM violates the hierarchical design idea of JAVA. I think that no matter what architecture design is modular, hierarchical thought is the foundation, so this basic principle we should abide by, for some new architecture mode, holding an objective attitude to learn can always improve their design level.

Please accept mybest wishes for your happiness and success !

Android Architecture Design –MVP Mode (2), how to reduce class explosion

Reference:

Tech.meituan.com/android_mvv…

www.jianshu.com/p/2fc41a310…

Zhuanlan.zhihu.com/p/23772285?…

Github.com/tianzhijiex…

www.open-open.com/lib/view/op…

Juejin. Cn/post / 684490…

Github.com/Kelin-Hong/…