MVC、MVP和MVVM都是为了解决界面呈现和逻辑代码分离而出现的模式,目的都是为了提高代码的复用率、降低代码的耦合度、便于模块测试、版本的迭代更新。
为什么是框架而不是设计模式?
框架是大智慧,用来对软件设计进行分工;设计模式是小技巧,对具体问题提出解决方案,以提高代码复用率,降低耦合度。框架通常是代码重用,而设计模式是设计重用,架构则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。
架构应该是一个范畴最大的概念,是最高层次的设计。一个架构设计中可能会用到多个框架和多个设计模式;而框架是针对共性抽象出来的半成品,这里面可能包含着多个设计模式;而设计模式就是解决单一问题的设计思路和解决方法。所以我们在做一个项目的时候首先出来的应该是架构,是对整个问题的一个总体上的设计,之后再会考虑运用什么样的框架和设计模式来实现我们的架构。
MVC:Model - View - Controller(模型 - 视图 - 控制器)
View 传送指令到 Controller;Controller 完成业务逻辑后,要求 Model 改变状态;Model 将新的数据发送到 View,用户得到反馈。也可以直接通过controller接受指令,View和Controller之间断开。
1. 用户可以向 View 发送指令(DOM 事件),再由 View 直接要求 Model 改变状态。
2. 用户也可以直接向 Controller 发送指令(改变 URL 触发 hashChange 事件),再由 Controller 发送给 View。
3. Controller 非常薄,只起到路由的作用,而 View 非常厚,业务逻辑都部署在 View。
在Android中,View:XML文件;Controller:Activity;Model:我们针对业务模型,建立的数据结构和相关的类,Model是与View无关,而与业务相关的。对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。
Android中MVC的缺点:View对应的XML文件实际能做的事情很少,很多界面显示由Controllor对应的Activity给做了,这样使得Activity变成了一个类似View和Controllor之间的一个东西。因为在Android开发中,Activity并不是一个标准的MVC模式中的Controller,它的首要职责是加载应用的布局和初始化用户界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。
总之:MVC中Activity中存在两部分内容: 业务相关和界面相关;并且View中的内容相对较少而Controller中的内容较多。MVC比较适用于快速开发的小型项目。
MVP:Model - View - Presenter(模型 - 视图 - 交互中间人)
MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,Presenter完全把Model和View进行了分离,而在MVC中View会直接从Model中读取数据而不是通过 Controller。并且Presenter与具体的View是没有直接关联的,而是通过接口进行交互,从而使得在变更View时候可以保持Presenter的不变,可以多次复用。
各部分之间的通信,都是双向的; View 与 Model 不发生联系,都通过 Presenter 传递; View 中不部署任何业务逻辑,Presenter负责所有逻辑。
在Android中,View:Activity;Presenter:作为View与Model交互的中间纽带,处理与用户交互的负逻辑。
MVP优点:
代码解耦;结构清晰;可复用;扩展性高;方便进行单元测试。
MVP缺点:
1、由于对视图的渲染放在了Presenter中,所以视图和Presenter的交互会过于频繁。还有一点需要明白,如果Presenter过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密。一旦视图需要变更,那么Presenter也需要变更了。比如说,原本用来呈现Html的Presenter现在也需要用于呈现Pdf了,那么视图很有可能也需要变更。
2、增加了很多的接口和实现类。代码逻辑虽然清晰,但是代码量要庞大一些。
所以MVP比较适用于中小型的项目。
Android中MVP与Activity、Fragment的生命周期
由于Presenter经常需要执行一些耗时的操作,如:网络请求,或其它异步操作。而Presenter持有Activity的引用,若果在网络请求结束之前Activity被销毁,那么由于网络请求还没有返回,Presenter一致持有该Activity的引用,使其无法被回收,从而导致内存泄漏。仅仅在onDestory函数中解除对Activity的引用是不够的,因为并不是在任何情况下Activity的onDestory都会被调用的。可以使用弱引用来避免,当一个对象只存在弱引用时,系统就可以回收该对象。
MVVM:Model - View - ViewModel
MVVM可以算是MVP的升级版,其中的VM是ViewModel的缩写,ViewModel可以理解成是View的数据模型和Presenter的合体,ViewModel和View之间的交互通过Data Binding双向绑定完成,而Data Binding可以实现双向的交互,这就使得视图和控制层之间的耦合程度进一步降低,关注点分离更为彻底,同时减轻了Activity的压力。(双向绑定:View的变动,自动反映在 ViewModel中)
MVVM与MVP唯一的区别是View和Model进行双向绑定,MVP中的View更新需要通过Presenter,而MVVM则不需要。此时,ViewModel角色需要做的只是业务逻辑的处理,以及修改修改View或者Model的状态。MVVM有点像ListView、Adapter、数据集的关系,这个Adapter就是ViewModel角色。
Android中的MVVM:
双向绑定:在XML中与数据绑定。看一个小例子,你就明白了一切,详细的知识请参考:http://blog.csdn.net/jdsjlzx/article/details/48133293
XML:
variable是一个变量,变量名是stu,类型是org.loader.androiddatabinding.Student。在xml中还可以导入包
Java:
DataBindingUtil类返回什么对象呢?它是一个自动生成的类的对象ActivityMainBinding,命名规则:把布局文件的首字母大写,并且去掉下划线,将下划线后面的首字母大写,加上Binding组成。binding.setXXX,这个XXX是什么呢?就是我们在xml中定义的那些变量首字母大写了。事件绑定:在xml中我们可以给button设置一个onClick来达到事件的绑定,现在DataBinding也提供了事件绑定,android:onClick="@{handlers.handleClick},定义了一个EventHandlers类型的handlers变量,并在onClick的时候执行EventHandlers的handleClick方法。注意的是,handlerClick(View view)方法需要一个View的参数。
Bean:
观察getName方法,我们使用了@Bindable注解,观察setName,我们调用了notifyPropertyChanged方法,这个方法还需要一个参数,这里参数类似于R.java,保存了我们所有变量的引用地址,这里我们使用了name。
总结
MVC -> MVP -> MVVM 这几个软件设计模式是一步步演化发展的,MVVM 是从 MVP 的进一步发展与规范,MVP 隔离了MVC中的 M 与 V 的直接联系后,靠 Presenter 来中转,所以使用 MVP 时 P 是直接调用 View 的接口来实现对视图的操作的,这个 View 接口的东西一般来说是 showData、showLoading等等。M 与 V已经隔离了,方便测试了,但代码还不够优雅简洁,所以 MVVM 就弥补了这些缺陷。在 MVVM 中就出现的 Data Binding 这个概念,意思就是 View 接口的 showData 这些实现方法可以不写了,通过 Binding 来实现。
MVC的Activity中存在两部分内容: 业务相关和界面相关,并且V中的内容相对少而C中的内容较多。 MVP: 将activity中的业务拆分。 MVVM: 将activity中的页面拆分。
参考文献:
http://www.androidchina.net/7274.html
http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html
https://baike.baidu.com/item/MVP模式/10961746