MVC:
Model: 应用数据和处理数据的逻辑;一般对应 JavaBean及一些repository
View: 屏幕上看见的对象就是View对象;一般对应 Xml 中定义的各类组件
Controller: 逻辑处理单元,视图与模型对象的联系纽带,响应 View 触发的各类事件、管理 Model 与 View 间的数据流动;Android 里一般对应 Activity、Fragment、Service。
缺点:
MVC完整的流程: MVC 流程图View 视图层对应xml布局文件,所做的事情相当有限,布局文件中的事件绑定,数据处理都是在acvitity中进行,造成 Acvitity 既像 View 又像 Controller。
什么是 MVP
MVP 与 MVC 最大的区别就在与将 Model 和 View 通过 Presenter 隔开了,不再允许其互相直接通信,而所有的消息都是通过 Presenter 这个中间人来传递。而这样做的目的主要是为了将数据和展示划出更明确的界限。
并不标准的 MVC 到 MVP 的一个转变,减少了 Activity 的职责,简化了 Activity中的代码,将复杂的逻辑代码提取到了 Presenter 中进行处理。与之对应的好处就是,耦合度更低,更方便的进行测试
各自职责:
- Model:负责定义数据(解决什么是数据)
- Presenter:负责在Model和View之间,从model里取出数据,格式化后在View上展示(解决如何把数据和用户界面放在一起)。
- View:负责担任一个被动界面,用于展示数据。(解决如何展示数据)
Presenter 作为中间者,同时拥有 View 和 Model 的引用,在它们之间起到桥梁作用,即 Presenter 会主动和 View 和 Model 进行通信。
而Model 和 View 必须是完全隔离的,不允许两者之间互相通信,保持对彼此的不感知,这样的好处是彻底将数据和展示分离来开,并且可以独立的为Model去做测试。
Model 在三者中是独立性最高的,Model不应该拥有对View的引用,而且Model也不需要保存对Presenter的引用,对于Presenter而言,Model只需要提供接口,等着Presenter来调用时返回相应数据即可,Model 也不应该去通知View,而是通知 Presenter 来间接的更新View的。
Presenter 和 Model:基于接口来通信,这样才能把 Model 和Presenter 的耦合度也降到最低,那么在需要改变 Model 内部实现,甚至彻底替换 Model 的时候,Presenter 则是无需随之改变的。这样做带来的另一个好处就是你可以通过 Mock 一个 Model 来对 Presenter 以及 View 做模拟测试了,从而提高了可测试性。
View 和 Presenter:View是需要拥有对Presenter的引用,但仅仅是为了将用户的操作和事件立即传递给Presenter,为了让 View 和 Presenter 耦合较低,View也只应该通过接口与 Presenter 通信,从而保证 View 是完全被动的,一方面它由用户的操作触发来和Presenter通信,另一方面它完全受 Presenter 控制,唯一需要做的事情就是如何展示数据。
三者之间的关系:
-
View 和 Model 之间没有联系
-
View 通过接口向 Presenter 来传递用户操作
-
Presenter 通过接口和 View/Model 来联系。
-
Model 不主动和 Presenter 联系,被动的等着 Presenter 来调用其接口
View <- 接口 <- Presenter ->接口 -> Model
View -> 接口 -> Presenter <- 接口 <- Model
为什么使用 MVP
在 MVC 中,XML视图功能太弱,所以 Activity 既要负责视图的显示又要加入控制逻辑,往往需要同时承担和 V 和 C 两部分职责,代码过于臃肿,不好维护和扩展,比如说当修改数据获取方式的时候,需要修改的地方太多,而且需要把整个业务逻辑全部看一遍,且容易修改错;而当使用的MVP模式时,只需要修改 Model 中获取数据的方式,因为 Presenter 层拿到的是 Model 的接口,只关心 Model 层返回的数据,至于你的数据是从网络还是数据库还是本地数据库文件获取的,根本不必关心。 MVP 让 Activity 成为真正的 View。
优点:
- 分层更加清晰明确
- 更利于扩展和维护
- 方便对于 Model 进行单独测试
缺点:
- 类比较多
- 由于对视图的渲染放在了 Presenter 中,所以视图和Presenter的交互会过于频繁。
- 如果 Presenter 过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密。一旦视图需要变更,那么Presenter也需要变更了
MVVM
ViewModel:
创建关联,将 Model 和 View 绑定起来,如此之后,我们 Model的更改,通过ViewModel 反馈给 View,从而自动刷新界面。DataBinding是一个实现数据和UI绑定的框架,是构建MVVM模式的一个关键的工具,它是支持双向绑定的。
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 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。
databinding
- gradle 中
dataBinding {
enabled true
}
-
xml 中
最外层使用 layout 标签,通过 data 标签将该 View 对于的 Model 导入进来,然后在控件中比如 TextView 的 text 属性就可以和该 Model 的属性绑定。
支持运算符操作。如三元
支持事件绑定。 -
Activity 中
ActivityMainTestBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main_test);
binding.setTest(testModel);
不需要写 findViewById 和 butterknife,只需要
android:id="@+id/tv"
TextView tv = binding.tv;
网友评论