MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。其中M层处理数据,业务逻辑等;V层处理界面的显示结果;C层起到桥梁的作用,来控制V层和M层通信以此来达到分离视图显示和业务逻辑层。
其实MVC在J2EE开发中应用是很多的,它将业务逻辑与界面分离开来,通过控制器将其连接,从而达到了很好的解耦效果,通过MVC编写的代码有利于后期的维护和改造。
在Android开发中,我们也是经常看到MVC框架模式的身影,例如我们开发Android端应用时,界面编写时在XML中,而我们经常回把网络访问数据独立出来,再通过Activity处理用户交互的问题,这就是一种MVC的思想。采用MVC模式的好处是便于UI界面部分的显示和业务逻辑,数据处理分开。下面具体以MVC的表现形式描述一下:
M层:适合做一些业务逻辑处理,比如数据库存取操作,网络操作,复杂的算法,耗时的任务等都在model层处理。
V层:应用层中处理数据显示的部分,XML布局可以视为V层,显示Model层的数据结果。
C层:在Android中,Activity处理用户交互问题,因此可以认为Activity是控制器,Activity读取V视图层的数据(eg.读取当前EditText控件的数据),控制用户输入(eg.EditText控件数据的输入),并向Model发送数据请求(eg.发起网络请求等)。
为方便理解,我下面举一个例子,由于MVC容易理解,也鉴于篇幅问题,这里只给出简短的伪代码,因为具体的代码也没有什么意义:我们通过一个获取天气预报数据的小项目来解读 MVC for Android
Controller控制器
从上面代码可以看到,Activity持有了ApiClient网络请求模型的对象,当我们需要获取数据时,只需要调用initData()方法。比如我们点击Button,Activity作为Controller控制层会处理View视图层,并调用ApiClient.getDataDetail方法,当Model模型处理数据结束后,通过接口onDataChanged通知View视图层数据处理完毕,View视图层该更新界面UI了。然后View视图层去更新界面。看到这里,我们会发现整个MVC框架流程就在Activity中体现出来了。
Model模型
这里ApiClient就是充当Model层的,专门用于处理网络数据请求,代码就不展示了,读者只要理解就行。 上面的例子中,Activity将View视图显示和Model模型数据处理隔离开了。activity担当contronller完成了model和view之间的协调作用。
那么我们为什么要这样实现,直接在Activity中实现网球请求不是更方便吗?
很多人可能会有这种疑问,可是大家想想,如果这种网络请求都在Activity中实现的话,一是不利于代码复用,而是后期维护起来是很困难的。比如我们现在的网络请求用的是Volley,以后想换成NoHttp实现的话,我们好需要修改每一个Activity类,这是不是很繁琐,看到这里我们就会发现MVC的好处了。
MVC简要总结:
在Android项目中,业务逻辑,数据处理等担任了Model(模型)角色,XML界面显示等担任了View(视图)角色,Activity担任了Contronller(控制器)角色。contronller(控制器)是一个中间桥梁的作用,通过接口通信来协同 View(视图)和Model(模型)工作,起到了两者之间的通信作用。
我们发现,其实控制器Activity主要是起到解耦作用,将View视图和Model模型分离,虽然Activity起到交互作用,但是Activity中有很多关于视图UI的显示代码,因此View视图和Activity控制器并不是完全分离的,也就是说一部分View视图和Contronller控制器Activity是绑定在一个类中的。所以MVC应用在Android中,它的解耦效果并不是十分的完美,当我们的APP逐渐变大时,我们还会发现我们的Activity和Fragment会越来越庞大。
因此如果我们开发的Android项目不是很庞大,用MVC框架模式还是比较理想的,如果我们的项目是比较庞大,而且后期经常需要修改维护的话,我更建议使用MVP框架模式,
完美的MVC应用场景应该是这样的:
有个Student Model, 关联StudentListView, StudentEditView.
对于StudentListView, Student Model提供Student的集合数据来显示StudentListView
对于StudentEditView, Student Model提供单个Student数据来展示StudentEditView并且响应StudentEditView的保存操作。
但是这只是完美的情况,实际应用中,在ListView上,不单单显示Student的信息,可能还需要这个Student的历史成绩,家庭情况, 老师信息。而这些是Student Model不能提供的。
也许我们可以扩展Student Model, 将Student Model能够提供的信息扩展,包含成绩信息等,这本身也可以。但是,如果Student显示的View,这个需要只是需要额外的成绩信息,另一个View只是需要额外的家庭信息,Student Model是不是有些疲于奔命,你能知道还会有多少个差异化的View的需求? 而且让逻辑端代码这样不断的修改来适应View端,好吗?
由于MVC的设计思想是从Model出发,而没有考虑到View端的复杂性,这样导致的问题是Model难以符合复杂多变的View端变化。
相对这点,MVP和MVVM就要好得多。它们都独立出了Presenter 和ViewModel来对应每个View。
MVC使用的误区
1.把Model理解成实体类(Entity),在MVC中Model应该包含2部分功能,一部分是处理业务逻辑,一部分是提供View显示的数据
2.把业务逻辑全部放在Controller端
这两个误区本质上都是对Model的作用不明导致的。
Model在MVC架构中起的作用非常重要,它应该是业务逻辑真正的实现层。所以Model的实际上是Business Model(业务模型)。而Controller仅仅起一个“桥梁”作用,它负责把View的请求转发给Model,再负责把Model处理结束的消息通知View。Controller是用来解耦View和Model的,具体一点说,就是为了让UI与逻辑分离(界面与代码分离)
在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。 在MVC模型里,更关注的Model的不变,而同时有多个View对Model的不同显示。所以,在MVC模型里,Model不依赖于View,但是 View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。