一. 前言
1. 介绍
MVVM全名是Model-View-ViewModel,MVVM可以看作MVP的升级版。
- Model:模型层,负责处理数据的加载或存储。与MVP中的M一样。
- View:视图层,负责界面数据的展示,与用户进行交互。与MVP中的V一样。
- ViewModel:视图模型,负责完成View于Model间的交互,负责业务逻辑-
2. 作用
降低View和控制模块的耦合,减轻了视图的压力。
3. 流程

- View与ViewModel进行绑定,能够实现双向的交互。ViewModel数据改变时,View会相应变动UI,反之亦然。
- ViewModel进行业务逻辑处理,通知Model去更新。
- Model数据更新后,把新数据传递给ViewModel。
二. MVC实例
还是以点击按钮对数字+1为例子,将其改造成MVVM模式。与MVP不同的地方是,ViewModel会跟View进行绑定。这里会用到Android的 Data Binding。关于Data Binding,可以看下这篇文章介绍:Data Binding Library。
使用的时候需要到对应模块的build.gradle文件中添加使用代码:

1. Model层
跟MVP的一样。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | public class NumModel {private int num = 0;
 
 public void add(ModelCallback callback){
 callback.onSuccess(++num);
 }
 
 
 
 
 public interface ModelCallback {
 void onSuccess(int num);
 void onFailed(int num);
 }
 }
 
 | 
2. View层
将根布局修改为layout,加入 Data Binding。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 
 | <?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android">
 
 <data class=".VmActivityBinding">
 <variable
 name="numVM"
 type="swu.xl.mvvmtest.NumViewModel" />
 </data>
 
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 android:gravity="center">
 
 <TextView
 android:id="@+id/tv_show"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:textSize="20sp"
 android:layout_marginBottom="10dp"
 android:text="@{numVM.num}"
 />
 
 <Button
 android:id="@+id/btn_add"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="点击+1"
 android:onClick="@{numVM.onClickAdd}"
 />
 
 </LinearLayout>
 </layout>
 
 | 
Build一下项目,生成一些需要的类。

在VmActivity中将View与ViewModel进行绑定。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | public class VmActivity extends AppCompatActivity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 
 
 
 VmActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
 
 
 NumViewModel numViewModel = new NumViewModel();
 binding.setNumVM(numViewModel);
 }
 }
 
 | 
3. ViewModel层
ViewModel负责业务逻辑处理,并且数据有更新直接通知View去更改。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 
 | public class NumViewModel extends BaseObservable {private String num;
 
 private NumModel numModel;
 
 public NumViewModel() {
 numModel = new NumModel();
 }
 
 
 
 
 @Bindable
 public String getNum() {
 return num;
 }
 
 public void setNum(String num) {
 this.num = num;
 
 
 notifyPropertyChanged(BR.num);
 }
 
 public void onClickAdd(View view){
 
 numModel.add(new NumModel.ModelCallback() {
 @Override
 public void onSuccess(int num) {
 setNum(num+"");
 }
 
 @Override
 public void onFailed(int num) {
 setNum("");
 }
 });
 }
 }
 
 | 
4. 运行结果

5. 源码
MVVMTest
三. MVP和MVVM的区别
ViewModel与View绑定后,ViewModel与View其中一方的数据更新都能立即通知到对方;Presenter需要通过接口去通知View进行更新。
四. MVC的优缺点
1. 优点
2. 缺点
数据绑定使得程序较难调试,界面出现异常时,有可能是 View 的代码有问题,也可能是 Model 的代码有问题。由于数据绑定使得数据能够快速传递到其他为止,因此要定位出异常就比较有难度了。
参考文章
Android框架模式——MVVM
DataBinding详细的使用方法及工作中常遇到的问题(一)
DataBinding 使用介绍
Android基础——框架模式MVVM之DataBinding的实践
DataBinding使用教程(三):各个注解详解