MVC、MVP、MVVM
MVC,MVP和MVVM都是常见的软件架构设计模式(Architectural Pattern),它通过分离关注点来改进代码的组织方式。不同于设计模式(Design Pattern),只是为了解决一类问题而总结出的抽象方法,一种架构模式往往使用了多种设计模式。
architectural [?ɑ?rk??tekt??r?l] 建筑学的,建筑上的 pattern [?p?t?rn] 模式,方式
MVC、MVP和MVVM不同部分是C(Controller)、P(Presenter)、VM(View-Model),而相同的部分则是MV(Model-View)。Model层用于封装和应用程序的业务逻辑相关的数据以及对数据的处理方法。View作为视图层,主要负责数据的展示。
1 MVC
通过Model&View完成了数据从模型层到视图层的逻辑。但对于一个应用程序,这远远是不够的,还需要响应用户的操作、同步更新View和Model。于是,在MVC中引入了控制器Controller,让它来定义用户界面对用户输入的响应方式,它连接模型和视图,用于控制应用程序的流程,处理用户的行为和数据上的改变。

- 模型层(
Model):用来存储业务的数据,一旦数据发生变化,模型将通知有关的视图。Model是与View无关, 而与业务相关的。对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的; - 视图层(
View):一般采用XML文件进行界面的描述`; - 控制层(
Controller):Android的控制层的重任通常落在了众多的Activity的肩上;
MVC允许在不改变视图的情况下改变视图对用户输入的响应方式,用户对View的操作交给了Controller处理,在Controller中响应View的事件调用Model的接口对数据进行操作,一旦Model发生变化便通知相关视图进行更新。
随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。
2 MVP
当我们将Activity复杂的逻辑处理移至另外的一个类(Presenter)中时,Activity其实就是MVP模式中的View,它负责UI元素的初始化,建立UI元素与Presenter的关联(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由Presenter处理)。
MVP的Presenter是框架的控制者,承担了大量的逻辑操作,而MVC的Controller更多时候承担一种转发的作用。因此在APP中引入MVP的原因,是为了将此前在Activty中包含的大量逻辑操作放到控制层中,避免Activity的臃肿。

- 模型层(
Model):负责存储、检索、操纵数据,有时也实现一个Model interface用来降低耦合; - 视图层(
View):负责显示数据,并向Presenter报告用户行为。与用户进行交互,在Android中体现为Activity; - 业务逻辑层(
Presenter):负责逻辑处理,从Model拿数据,回显到UI层,响应用户的行为;
google todo-mvp加入契约类来统一管理View与Presenter的所有的接口,这种方式使得View与Presenter中有哪些功能,一目了然
优点:
- 分离视图逻辑和业务逻辑,降低了耦合,修改视图而不影响模型,不需要改变
Presenter的逻辑。模型与视图完全分离,我们可以修改视图而不影响模型; - 视图逻辑和业务逻辑分别抽象到了
View和Presenter的接口中,Activity只负责显示,代码变得更加简洁,提高代码的阅读性; Presenter被抽象成接口,可以有多种具体的实现,所以方便进行单元测试;
Presenter是通过interface与View(Activity)进行交互的,这说明我们可以通过自定义类实现这个interface来模拟Activity的行为对Presenter进行单元测试,省去了大量的部署及测试的时间(不需要将应用部署到Android模拟器或真机上,然后通过模拟用户操作进行测试)
缺点:
- 那就是对
UI的操作必须在Activity与Fragment的生命周期之内,更细致一点,最好在onStart()之后onPause()之前,否则极其容易出现各种异常,内存泄漏; Presenter与View之间的耦合度高,app中很多界面都使用了同一个Presenter 。一旦需要变更,那么视图需要变更了;
MVP如何设计避免内存泄漏?
MVP模式在封装的时候会造成内存泄漏,因为Presenter层,需要做网络请求,所以就需要考虑到网络请求的取消操作,如果不处理,Activity销毁了,Presenter层还在请求网络,就会造成内存泄漏。
如何解决MVP模式造成的内存泄漏?只要Presenter层能感知Activity生命周期的变化,在Activity销毁的时候,取消网络请求,就能解决这个问题。
下面开始封装Activity和Presenter。定义IPresenter声明Activity(Fragment)生命周期中的各个回调方法:
public interface IPresenter {
<U extends IUI> void init(BaseActivity activity, U ui);
void onUICreate(Bundle savedInstanceState);
void onUIStart();
void onUIResume();
void onUIPause();
void onUIStop();
void onUIDestroy();
void onSaveInstanceState(Bundle outState);
void onRestoreInstanceState(Bundle savedInstanceState);
}
封装BaseActivity拥有一个protected P mPresenter实例,类型写成泛型,protected修饰,子类实现构造方法中,对mPresenter进行实例化:采用反射的形式(避免让子类进行实例化,繁琐):
public abstract class BaseMVPActivity<P extends IPresenter> extends BaseActivity {
protected P mPresenter;
public BaseMVPActivity() {
this.mPresenter = createPresenter();
}
protected P createPresenter() {
ParameterizedType type = (ParameterizedType) (getClass().getGenericSuperclass());
if (type == null) {
return null;
}
Type[] typeArray = type.getActualTypeArguments();
if (typeArray.length == 0) {
return null;
}
Class<P> clazz = (Class<P>) typeArray[0];
try {
return clazz.newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onDestroy() {
mPresenter.onUIDestroy();
super.onDestroy();
}
}
封装BasePresenter。定义BasePresenter,页面销毁的回调里面。处理网络请求定义一个集合,把每次网络请求装载到集合里面,在页面销毁的时候,取消所有的网络请求。防止内存泄漏。
public abstract class BasePresenter<U extends IUI> implements IPresenter {
@Override
public void onUIDestroy() {
}
}
MVC与MVP区别
View与Model并不直接交互,而是通过与Presenter交互来与Model间接交互。而在MVC中View可以与Model直接交互。MVP隔离了MVC中的M与V的直接联系后,靠Presenter来中转,所以使用MVP时P是直接调用View的接口来实现对视图的操作的。

3 MVVM
MVVM可以算是MVP的升级版,其中的VM是ViewModel的缩写,ViewModel可以理解成是View的数据模型和Presenter的合体,ViewModel和View之间的交互通过Data Binding完成,而Data Binding可以实现双向的交互,这就使得视图和控制层之间的耦合程度进一步降低,关注点分离更为彻底,同时减轻了Activity的压力。
DataBinding用来实现View层与ViewModel数据的双向绑定,Data Binding减轻原本MVP中Presenter要与 p 和 View 互动的职责

- 模型层(
Model):即数据模型,用于获取和存储数据; - 视图模型层(
ViewModel):与Presenter大致相同,都是负责处理数据和实现业务逻辑,但ViewModel层不应该直接或者间接地持有View层的任何引用; - 视图层(
View):包含布局,以及布局生命周期控制器(Activity/Fragment);
MVVM的本质是数据驱动,把解耦做的更彻底,ViewModel不持有View。
View产生事件,使用ViewModel进行逻辑处理后,通知Model更新数据,Model把更新的数据给ViewModel, ViewModel自动通知View更新界面,而不是主动调用View的方法
MVVM的优点:
核心思想是观察者模式,它通过事件和转移View层数据持有权来实现View层与ViewModel层的解耦。
- 耦合度更低,复用性更强,没有内存泄漏;
- 结合
Jetpack,写出更优雅的代码;
缺点:
ViewModel与View层的通信变得更加困难了,所以在一些极其简单的页面中请酌情使用,在使用MVP这个道理也依然适用。
参考
https://blog.csdn.net/lihaoxiang123/article/details/78977181
https://blog.csdn.net/caijunfen/article/details/78478438
|