MVC->MVP->MVVM架构完整演变过程剖析
在之前对于MVP这种架构风格已经进行了深入的学习了,接下来则打算学习一下MVVM这种架构,MVC、MVP、MVVM这三者基本上会被人一起问到的,而对于MVVM,google官方推出了一个dataBinding的MVVM的框架,而从学习的角度直接上框架并非是一个非常好的学习方式,所以这次就手把手的一步步通过一个小案例来实现MVVM框架,对其原理有一个本质的了解,这样在下一次学习dataBinding时也能做到心中有数。
MVC:
思想:
架构理解:
对于上图的理解,简单描述整个过程就是用户触发了View的一个事件,然后则会转到Controller中进行处理,而它又会去操作Model,最终Model处理完了会更新到UI上来。这里用一个伪代码来模拟一下这个过程:
而其实有些MVC会是这样的一个关系:
具体实现:
接下来则回到Android的代码上来,先来简单搭个框架:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <EditText android:id="@+id/et_data1" android:layout_width="match_parent" android:layout_height="wrap_content" /> <EditText android:id="@+id/et_data2" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btn_save" android:layout_width="100dp" android:layout_height="wrap_content" android:text="save" /> </LinearLayout>
没啥好解释的,默认Android的这个代码框架就属于MVC风格的,这个都耳熟能详了,这里还是啰嗦一下:对于V来说就是我们的布局文件,而M则是DateCenter这个类,而C则是MainActivity。那为啥会出现MVP、MVVM这种新的框架出来呢?因为目前MVC框架中的Activity太重了,跟M和V都进行耦合在一块了,所以MVP出现了。
MVP:
思想:
架构理解:
其中可以看到跟MVC中最大的区别在于MVP的Model和View之间没有引用了,然后之前的Controller变成了Presenter了。
具体实现:
接下来咱们来将它改造成MVP,首先先来新建一个P:
然后它会操作Model,所以这里将这个代码牵移到P中:
此时Activity调整为:
此时一个基本的MVP就出现了,其中“View跟Controller给拆开了,并提取出了一个Presenter”,目前这个基本的MVP框架中P是直接持有了具体Activity的引用,然后目的是用来调用它里面的刷新界面的方法:
很明显对于P来说不需要用到MainActivity中的所有信息,只需要知道这个界面是如何更新UI的就行了,所以直接持有Activity的引用设计不是太合理,面向接口编程是最提倡的,也就是能只获取最小的信息则就获取最小的,这样会解耦,所以咱们将其抽象成一个接口,里面会存放各个跟UI相关的操作接口:
思考:在上面中加粗了一句话“View跟Controller给拆开了,并提取出了一个Presenter”,那能否不提一个Presenter,而达到同样的效果呢?其实是可以的,而这种写法在实际工作中也是很频繁的,下面改装一下,这里先将建几个包将其分开一下:
而这里则对MvcActivity传统的写法进行调整一下:
怎么能让控件层与View之间耦合不那么紧呢?其实就是想办法把这段代码给去掉:
其实就是将这个设置封装到View里面既可:
package com.android.mvc_mvp_mvvm_demo.mvc;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.EditText;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
import com.android.mvc_mvp_mvvm_demo.R;
public class DataView extends LinearLayout {
private EditText et_data1;
private EditText et_data2;
public DataView(Context context) {
super(context);
}
public DataView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public DataView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void showData(String[] data) {
et_data1.setText(data[0]);
et_data2.setText(data[1]);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
et_data1 = findViewById(R.id.et_data1);
et_data2 = findViewById(R.id.et_data2);
}
}
为啥要改上面这种比较简单的代码呢?其实这里是要来对于很多人都说的:“MVP要比MVC要好,MVC的View和Controller都混到一块”这样的观点持怀疑态度,很明显通过上面的这样改良,也没有提取出一个P,跟MVP的效果差不多呀, 那为啥要说MVP比MVC要好呢?可能有些人会说MVP不是会提取出一个View的接口嘛,那对于上面改良的这种代码也可以提取呀,下面试一下:
所以其实对于MVC和MVP框架本质来说其实是一样的,当然细节会有不同,这种观点其实没必要较真,只是为了了解其了本质才这样挖掘的,而平常在讨论这俩框架的区别时,还是可以说:“Android自带的框架就是MVC,而抽出来一个P层的则是MVP”。
MVVM:
接下来则来看最后一种架构了,这种目前还木有在真实项目中用过,但是对于它的了解也早就有所耳闻,相比MVP而言,它的数据如果发生变化了会立马反馈到UI上,而不需要通过回调通知UI进行刷新,反过来如果UI更新了数据状态也会自动到去将Model中的数据给自动更新 。
思想:
具体实现:
先来新建一个ViewModel:
此时Activity就可以这样来调用了:
接下来要实现数据自动显示在界面上该如何修改呢?怎么明显Activity跟ViewModel需要进行绑定才行,所以新建一个类:
在这里面则需要监听textView和text的变化,对于TextView的变化监听有现成的API这个不用操心,但是对于第二个参数text很显然不能,所以此时我们得将ViewModel中的这块得封装一下才行:
具体修改如下:
此时回到ViewBinder类中:
哦,原来双向绑定的核心是这么搞的,就是哪方改变了再通知另一方,好接下来咱们再回到ViewModel中:
接下来则可以进行Activity与ViewModel的绑定了,先来在ViewModel定义一个绑定接口供Activity来调用:
好,接下来调用一下:
至此一个简单的MVVM框架就搭建完了,说实话还是有些麻烦的,不过好在Google针对MVVM推出了成熟的框架,如开篇有说,DataBinding,商用的话基本上会基于这个框架来进行MVVM的开发,这次对于MVVM的核心原理了解了之后,下一次就准备来学习一下DataBinding框架的使用及原理啦。