Original statement: This article is an original article, it is strictly prohibited to reprint without the consent of the blogger.

Abstract: It’s been a year since Google launched DataBinding, and there are many tutorials online. One serious problem with most of the tutorials I’ve read about MVVM implementation on Android is that most of the articles on MVVM are just introductions to DataBinding. In these tutorials, the Binding class (or entity class) generated by DataBinding is almost invariably referred to as the ViewModel layer. One major drawback of both approaches is that as a ViewModel layer, there is almost no control. Here, I present a summary of how to implement the MVVM pattern on Android with DataBinding.

What is the MVVM pattern?

MVVM mode refers to model-view-viewModel. As readers of my MVP article will have noticed, no matter how abstracted, we have to deal with some logic in our View layer. The View in MVVM mode is to completely abstract the state and behavior of the View, and give the control of logic and interface to the ViewModel. MVVM consists of the following three core components:

  • Model:Used to capture the business data model
  • View:Defines the layout and appearance of the interface
  • ViewModel: Logic control layer, responsible for processing data and processing business logic in View layer

The following is the MVVM model adopted by the author:

As can be seen, the MVVM model diagram and online introduction of MVVM is different, the following will be based on this model diagram to introduce MVVM in Android.

DataBinding profile

Those familiar with DataBinding can skip this section

DataBinding is a data binder that binds data to a View and then automatically refreshes the View as the data changes. This DataBinding is the key to implementing the MVVM mode.

The introduction of DataBinding

To introduce DataBinding, we simply add the following code to build.gradle in the Module.

android{  
....  
    dataBinding{  
        enabled true  
    }  
}Copy the code

Use DataBinding

Note: THIS is just one of the ways to use DataBinding. More detailed tutorials are available online, as the focus of this article is not DataBinding.

The DataBinding layout file is a little different from the regular layout file. The root tag of the DataBinding layout file is the Layout tag. Layout contains a data element and a View element, which is the layout file without DataBinding. Here’s the sample code:

  
  
      
  
          
  
      
  
      
  
          
  
          
  
      
Copy the code

The user in the data element is our custom user entity class. When we set the user class in DataBinding, our two texts will automatically set the value of Text.

UserBean entity class code:

public class UserBean { public ObservableField name = new ObservableField<>(); public ObservableField sex = new ObservableField<>(); public ObservableField age = new ObservableField<>() ; Public UserBean(){name.set(" UserBean "); Sex. Set (" male "); age.set(19); }}Copy the code

This entity class is a bit special, and the element inside it is the ObservableField class of DataBinding, which automatically notifies the View of a refresh when a value in our entity class changes. So when using DataBinding, I recommend using ObservableField to define our entity class.

After that, we just need to bind layout to the Activity. Here is the code to use:

ActivityTesBinding activityTesBinding = DataBindingUtil.setContentView(this,R.layout.activity_tes);  
UserBean user = new UserBean();  
activityTesBinding.setUser(user);Copy the code

When using DataBinding, we set the layout using the setContentView() method of the DataBindingUtil utility class, which is a little different from the usual setup method. According to our theory, after we set the user, our layout TextView will be displayed as “Zhang SAN” and “Male”. I’m not going to do it here, but you can try it. It’s very simple.

Ok, so that’s a brief introduction to DataBinding, but you should search for more details. DataBinding has many more interesting features that you should try out after reading this article.

Limitations of most MVVM tutorials

One serious problem with most of the tutorials I’ve read about MVVM implementation on Android is that most of the articles that describe MVVM are just introductions to DataBinding. In these tutorials, the DataBinding generated Binding class (ActivityTesBinding in the previous section) or entity class (UserBean) are almost invariably referred to as the ViewModel layer.

One major drawback of both approaches is that as a ViewModel layer, there is almost no control. If you want to add other extensions, they almost always need to be implemented in the View layer of activities, fragments, etc. Not only does this fail to decouple the code, but if a page handles too much functionality, the code becomes very unreadable.

So how do we use the MVVM pattern correctly on Android? Look at the next chapter

How to use MVVM mode correctly on Android

In MVVM mode, DataBinding should be used as a binder to bind entity classes to the View layer, and our business logic and View control should be abstracted from our ViewModel layer. The method is very simple, we simply need to pass our Binding class to our ViewModel layer to achieve control of the View layer through the ViewModel layer. Let’s take a look at the optimized layout code.

activity_main.xml :

  
  
      
  
          
  
              
  
          
  
          
  
          
  
      
  
Copy the code

content_main:

  
  
      
          
  
      
  
      
  
          
  
              
  
          
  
          
  
              
  
          
  
  
          
  
              
  
          
  
        Copy the code  
  
          
      
  
Copy the code

Here again, MD style interface design, but now we’ll focus on the code in content_main. You can see that the layout code is similar to what we saw in the previous section, but we have introduced a class called MainViewModel, which is the ViewModel class I mentioned. Android :onClick=”@{viewModel.applyUser}”; android:onClick=”@{viewModel.applyUser}”; And our User class is also referenced through the ViewModel. This is just one application of the ViewModel here. Let’s look at the code in the Activity and ViewModel.

MainActivity:

public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); / / create the ViewModel ActivityMainBinding ActivityMainBinding = DataBindingUtil. The setContentView (this, R.l ayout. Activity_main); MainViewModel mainViewModel = new MainViewModel(this,activityMainBinding); }Copy the code

MainActivity code is very simple, its core is to create the MainViewModel line, the other logic is handed over to the ViewModel processing. When we encounter business that cannot be handled inside the ViewModel (such as menu monitoring, etc.), we can do so by calling ViewModel methods in the View layer.

MainViewModel:

public class MainViewModel { private ActivityMainBinding activityMainBinding; private ContentMainBinding contentMainBinding; private AppCompatActivity activity; private UserBean user; public MainViewModel(AppCompatActivity activity, ActivityMainBinding activityMainBinding){ this.activity = activity; this.activityMainBinding = activityMainBinding; this.contentMainBinding = activityMainBinding.contentMain; init(); } public void init(){ activity.setSupportActionBar(activityMainBinding.toolbar); activityMainBinding.fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); }}); user = new UserBean(); contentMainBinding.setViewModel(this); } public void applyUser(View v){snackbar.make (v," succeeded ", snackbar.length_short).setAction("Action",null).show(); user.name.set(contentMainBinding.name.getText().toString()); user.sex.set(contentMainBinding.sex.getText().toString()); user.age.set(Integer.valueOf(contentMainBinding.age.getText().toString())); }}Copy the code

Note the following line in the above code:

contentMainBinding.setViewModel(this);
Copy the code

This code binds our ViewModel layer to a Layout file in the View layer. This allows a Layout in the View layer to call methods in the ViewModel. In this case, the button control calls the public void applyUser(View V) method.

The code is simple, and the core idea of this solution is:

  1. The Binding instance is generated from DataBinding in the View layer
  2. The View layer passes the generated Binding instance to the ViewModel layer
  3. The ViewModel layer binds a View layout to a ViewModel by Binding itself to a Binding instance.

Another advantage of this method is that we only need to introduce the ViewModel into the data tag of the Layout file, and other data objects are processed in the ViewModel.

Let’s take a look at the Demo

Initialization:

Reassign to User:

Some misinterpretations of MVVM on the Internet

In addition to the misinterpretation of using Binding as the ViewModel layer mentioned above, there is another pattern that you notice that is the so-called MVPVM pattern. The core idea of this model is to add the Presenter layer on top of MVVM. The Presenter and ViewModel layers are both logical control layers. There is no need to have two layers for the same function. The second thing I think is that having three layers in your APP is pretty good, but having four layers is unmanageable and complicates your code because you can’t differentiate between Presenter and ViewModel. So I recommend that you never use the so-called MVPVM pattern for development. MVVM already meets our development needs very well.

summary

This is the end of MVVM on Android, and readers of my MVP schema framework design will know that this is just the beginning. So I will write a series of articles on how to design an MVVM framework. Before writing this series of articles, there will be an introduction to the basic technologies and some technical solutions for interested readers. Same rules, release Demo download address: github.com/DobbyTang/M…