前言
今天就来聊聊和它相关的一个架构MVVM的话题。对于这2个东西,我们需要知道,Databinding 是一种框架,MVVM是一种架构,一种模式。DataBinding是一个实现数据和UI绑定的框架,是实现MVVM模式的工具,而MVVM中的VM(ViewModel)和View可以通过DataBinding来实现数据绑定(目前已支持双向绑定)。
既然已经开始聊MVVM了,那笔者也不妨和大家多聊一点,这里不妨对比一下Android App的3种设计架构:MVC、MVP、MVVM,来聊一下我个人在开发中的一些看法和思考。
1.为什么要在我们的项目中用架构或者模式?
这是一个沉重的问题,之前有小伙伴跟我说:没必要在项目中使用架构或者模式,这样做只是为了刻意在写,可以追求模式罢了。我微微一笑,他一定是没有做过大一点的项目,他一定是没有经历过痛苦的需要的更改,没有看见过经过多次迭代过后Activity变得异常混乱。
而我的理解是这样的:使用架构的目的是使程序模块化,做到模块内部的高聚合和模块之间的低耦合,使得程序在开发的过程中,开发人员只需要专注于一点,提高程序开发的效率,而且最重要的一点,架构和模式并不是说让你的代码量更少了,往往可能还会增大,但是它帮你在逻辑上更简单的了,很好的定义了单一原则,提供了更好的扩展性,方便定位问题以及后续需求变更时不至于满篇的去改一大堆东西。
对于不同量级的工程,具体架构的实现方式必然是不同的,切忌为了设计而设计,为了架构而架构,试想想,如果你的项目只有几个Java文件来做业务逻辑,还要什么架构,撸起袖子就是写,只需要做好模块和层次的划分就可以了。
2.MVC
视图层(View)
对应于xml布局文件,
控制层(Controller)
Android的控制层是由Activity来承担的,Activity本来主要是作为初始化页面,展示数据的操作,但是因为XML视图功能太弱,所以Activity既要负责视图的显示又要加入控制逻辑,承担的功能过多,在复杂一点的页面Activity代码量达到1000+也就不足为奇了。
模型层(Model)
我们针对业务模型,建立的数据结构和相关的类,它主要负责网络请求,数据库处理,I/O的操作。
3.MVP
在Android开发中,Activity并不是一个标准的MVC模式中的Controller,本来它的首要职责是加载应用的布局和初始化用户界面,接受并处理来自用户的操作请求,进而作出响应。在MVC模式下随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。
视图层(View)
负责绘制UI元素、与用户进行交互,对应于xml、Activity、Fragment、Adapter
模型层(Model)
负责存储、检索、操纵数据,一般包含网络请求,数据库处理,I/O流。
控制层(Presenter)
Presenter是整个MVP体系的控制中心,作为View与Model交互的中间纽带,处理View于Model间的交互和业务逻辑。
从去年到现在,MVP的设计思想在项目中用得比较多,它的具体实现就是接收到View的请求,从Model层获取数据,将数据进行处理,通过View层的接口回调给Activity或者Fragment。MVP能够让Activity成为真正的View,只做UI相关的事。它的优点还是很多的,不然也不会有这么多人喜欢它的,优点如下:
1、模型与视图完全分离,我们可以修改视图而不影响模型;
2、项目代码结构(文件夹)清晰,一看就知道什么类干什么事情;
3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁
4、协同工作(例如在设计师没出图之前可以先写一些业务逻辑代码或者其他人接手代码改起来比较容易)
尽管这样,MVP模式也有不足之处,不然也不会推出MVVM了,缺点如下:
Presente层与View层是通过接口进行交互的,View层可能会有大量的接口,因为有可能好几个Activity都是去实现同一个View接口,那么所有用到的Activity都要去实现所有的方法(不管你是否用到),而且如果后面有些方法要删改,Presenter和Activity都要改动,比较麻烦;
MVP把Activity相当的一部分责任放到了Presenter来处理,复杂的业务同时也可能会导致P层太大,一旦业务逻辑越来越多,View定义的方法越来越多,会造成Activity和Fragment实现的方法越来越多,依然臃肿。
4.MVVM
终于轮到今天的主角出场了,MVVM模式不是四层,任然是3层,分别是Model、View、ViewModel
Model :负责数据实现和逻辑处理,类似MVP。
View : 对应于Activity和XML,负责View的绘制以及与用户交互,类似MVP。
ViewModel : 创建关联,将model和view绑定起来,如此之后,我们model的更改,通过viewmodel反馈给view,从而自动刷新界面。
通常情况下,数据的流向是单方面的,只能从代码流向UI,也就是单向绑定;而双向绑定的数据流向是双向的,当业务代码中的数据改变时,UI上的数据能够得到刷新;当用户通过UI交互编辑了数据时,数据的变化也能自动的更新到业务代码中的数据上。而DataBinding是一个实现数据和UI绑定的框架,是构建MVVM模式的一个关键的工具,它是支持双向绑定的。
下面通过一张图来来看看MVVM的各层是如何协同工作的。
下面就一起来看看他们的职责和协同工作的原理。
Model
Model层就是职责数据的存储、读取网络数据、操作数据库数据以及I/O,一般会有一个ViewModel对象来调用获取这一部分的数据。
View
我感觉这里的View才是真正的View,为什么这么说?View层做的仅仅和UI相关的工作,我们只在XML、Activity、Fragment写View层的代码,View层不做和业务相关的事,也就是我们的Activity 不写和业务逻辑相关代码,一般Activity不写更新UI的代码,如果非得要写,那更新的UI必须和业务逻辑和数据是没有关系的,只是单纯UI逻辑来更新UI,比如:滑动时头部颜色渐变、editttext根据输入内容显示隐藏等,简单的说:View层不做任何业务逻辑、不涉及操作数据、不处理数据、UI和数据严格的分开。
ViewModel
ViewModel 只做和业务逻辑和业务数据相关的事,不做任何和UI、控件相关的事,ViewModel 层不会持有任何控件的引用,更不会在ViewModel中通过UI控件的引用去做更新UI的事情。ViewModel就是专注于业务的逻辑处理,操作的也都是对数据进行操作,这些个数据源绑定在相应的控件上会自动去更改UI,开发者不需要关心更新UI的事情。
总结
View层的Activity通过DataBinding生成Binding实例,把这个实例传递给ViewModel,ViewModel层通过把自身与Binding实例绑定,从而实现View中layout与ViewModel的双向绑定。mvvm的缺点数据绑定使得 Bug 很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。
该文章转自:http://mp.weixin.qq.com/s/L3XPJ0FPPKFVIpXf-_D6ZQ