The MVVM pattern divides the application into three layers:
Model layer
Mainly responsible for data supply. The Model layer provides data structures for business logic (e.g., entity classes), provides data retrieval (e.g., from local databases or remote networks), and provides data storage.
The View layer
Mainly responsible for the display of the interface. The View layer does not involve any business logic processing, it holds references to the ViewModel layer and notifies the ViewModel layer when business logic processing is needed.
The ViewModel layer
Mainly responsible for business logic processing. The ViewModel layer does not involve any view operations. The View layer can be bound to the Data in the ViewModel layer through the official Data Binding library. The change of Data in the ViewModel layer can be automatically notified to the View layer for update, so the ViewModel layer does not need to hold the reference of the View layer. The ViewModel layer can be seen as a combination of the View layer’s data model and the Presenter layer.
The biggest advantage of the MVVM pattern is that the ViewModel layer does not hold references to the View layer. This further reduces coupling and changes to the View layer code do not affect the ViewModel layer. When the View layer changes, the ViewModel layer does not need to change as long as the data bound to the View layer stays the same. No more boilerplate code. With the official Data Binding library, the UI and Data can be bound without having to write a lot of findViewById() and manipulation view code. Greatly improve the development efficiency of UI interface data binding in the development process!
We’ll start with the basic MVVM architecture, which we’ll call the entry-level version of MVVM, and encapsulate the implementation around Databinding and ViewMode, ditching the annoying findViewById and ButterKnife approach to view operations.
The first step is to create a blank project. At the entry level, we will divide the project into package structures:
- The activity layer or fragment layer is used to store activities or fragments.
- The VM layer is used to hold the ViewModel;
- Presenter layer is used to store data operations and network interaction logic.
Don’t forget to enable databinding so that we can reduce the view code by associating databinding with the project Module:app gradle file:
android { //... Omit a bunch of default configurations dataBinding {enabled = true}}Copy the code
After enabling the databinding function, we go back to the layout file we created. The default layout looks like this:
Select the root directory, Alt +emter or click on the bulb and select the first Convert to Data Binding Layout. AS will automatically Convert the layout file to the databinding structure we need:
<? The XML version = "1.0" encoding = "utf-8"? > <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> <! <variable name="viewModel" type="com.jf.mvvm.vm.MainVM" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".activity.MainActivity"> <TextView android:id="@+id/txv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{viewModel.title}" tools:text="txv_title" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/txv_title2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{viewModel.title2}" tools:text="txv_title2" app:layout_constraintTop_toBottomOf="@+id/txv_title" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:layout_marginTop="20dp"/> <Button android:id="@+id/btn_test" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@+id/txv_title2" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" Android :layout_marginTop="20dp" Android :onClick="@{viewModel::onTestClick}" Android :text=" test it "/> </androidx.constraintlayout.widget.ConstraintLayout> </layout>Copy the code
Attach our basic VM file, which is a normal Java class that provides a getter method. By default, databinding can directly obtain the getters in the VM file and the property values of public:
Public class MainVM{// MainPresenter can communicate with database and background. Private MainPresenter = new MainPresenter(); Public String title2 = "Title2 can also be displayed "; Public String getTitle(){return "This is what textView displays "; } public void onTestClick(View view){ Log.d("mvvm","onTestClick!!!!" ); }}Copy the code
To correlate the VM and layout files, we need to call in the MainActivity DataBindingUtil. The setContentView () method, and bind MainVM into the layout file, Fragments can be created through databindingutil.inflate (inflater, layoutRes, container,false); To bind the page layout:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
binding.setViewModel(new MainVM());
}
Copy the code
Running the APP project, we can see the results of our initial Databinding based MVVM project:
Com.jf. MVVM D/ MVVM: onTestClick!!!!
Let’s update the code again to associate clicks with data in the VM:
Public class MainVM{public String title2 = "the value here can also be displayed "; private MainPresenter mainPresenter = new MainPresenter(); public String getTitle(){ if(!" Equals (title2)){return "Change my value too!" ; } return "This is what textView displays "; } public void onTestClick(View View){title2 = "My value has changed!" ; Log.d("mvvm","onTestClick >>> "+title2 + " >>> "+getTitle()); }}Copy the code
After clicking, nothing happens to the page, but the value recorded in our log is successfully updated:
OnTestClick >>> My value has changed! >>> My value changes too!Copy the code
Understand after use Databinding, we know that if you want to update the value and synchronous to the UI, we need to do this, will inherit androidx VM file. Databinding. BaseObservable, and on the need to inform the binding data add @ Bindable, We can do this by calling notifyPropertyChanged(br.title); To tell the UI to refresh the corresponding property value (title is the target property value) :
Public class MainVM extends BaseObservable {public class MainVM extends BaseObservable {public class MainVM extends BaseObservable {public class MainVM extends BaseObservable { Private MainPresenter = new MainPresenter(); @bindable public String title2 = "Title2 can also be displayed "; @Bindable public String getTitle(){ if(!" Equals (title2)){return "Change my value too!" ; } return "This is what textView displays "; } public void onTestClick(View View){title2 = "My value has changed!" ; Log.d("mvvm","onTestClick >>> "+title2 + " >>> "+getTitle()); notifyPropertyChanged(BR.title); notifyPropertyChanged(BR.title2); }}Copy the code
After completing the above improvements, we run the APP again and click the test button. We will find that the values displayed on the page have been successfully changed as we expected!
So far, our most rudimentary and simple MVVM pattern is set up!
Update continuously, public number: programmer cat