type
status
date
slug
summary
tags
category
icon
password
😀
一直想学一下MVP和MVVM,网上看过好多文章降的都比较片面,这一部分的内容确实很多,尤其是MVVM,涉及到了LiveData、ViewModel,这篇文章尽可能全的把这些都讲到。

1 MCV

1.1 介绍

Model(模型):建立的数据结构和相关的类,它主要负责网络请求,数据库处理,I/O的操作。
View(视图):用户界面。对应于xml布局文件和java代码动态view部分
Controller(控制器):业务逻辑层。MVC中Android的控制层是由Activity来承担的,Activity本来主要是作为初始化页面,展示数据的操作,但是因为XML视图功能太弱,所以Activity既要负责视图的显示又要加入控制逻辑,承担的功能过多。
notion image
 

1.2代码结构

notion image
Callback是根据View或者Controller调用Model时回调使用
BaseModel顾名思义就是所有业务逻辑model的父类,这里的onDestroy()方法用于跟activity或者fragment生命周期同步,在destroy做一些销毁操作
SampleModel是业务逻辑的具体实现
Activity的代码
整个流程:
button点击事件的触发:View→Controller
获取用户信息事件的触发:Controller→Model
绑定用户信息到View:Controller→View

1.3 总结

  1. 具有一定的分层,model彻底解耦,controller和view并没有解耦
  1. 层与层之间的交互尽量使用回调或者去使用消息机制去完成,尽量避免直接持有
  1. controller和view在android中无法做到彻底分离,但在代码逻辑层面一定要分清
  1. 业务逻辑被放置在model层,能够更好的复用和修改增加业务

2 MVP

2.1 介绍

MVP分为3层:Model、View、Presenter,与MVC相比唯一的差别是Model和View之间不进行通讯,都是通过Presenter完成。实现了了Controller和View完全解耦
notion image

2.2 代码结构

notion image
代码结构延续MVC,BasePresenter类似于MVC中的BaseModel,主要负责业务逻辑的实现。google的MVP实现方案是把业务逻辑放在presenter中,弱化Model。
BaseView是所有View的父类,将android中的view抽象话出来,只有跟view相关的操作都由baseView的实现类去完成。
Contract 契约类这是Google MVP与其他实现方式的又一个不同,契约类用于定义同一个界面的view的接口和presenter的具体实现。好处是通过规范的方法命名和注释可以清晰的看到整个页面的逻辑。
这里的SampleActivity实现了SampleContract.View只是作为View存在的。虽然看起来,跟MVC中的实现很相似,但却有本质的区别。mPresenter为Model和View之间交互的桥梁。Presenter跟View相互持有,这里SampleActivity实现了SampleContract.View,mPresenter作为SampleActivity的成员变量,SampleActivity当然持有mPresenter,由于mPresenter是非静态的成员变量,因此默认持有SampleActivity的引用。

2.3 总结

通过引入接口BaseView,让相应的视图组件如Activity,Fragment去实现BaseView,实现了视图层的独立,通过中间层Preseter实现了Model和View的完全解耦。MVP彻底解决了MVC中View和Controller傻傻分不清楚的问题,但是随着业务逻辑的增加,一个页面可能会非常复杂,UI的改变是非常多,会有非常多的case,这样就会造成View的接口会很庞大。

3 MVVM

3.1 介绍

MVP中我们说过随着业务逻辑的增加,UI的改变多的情况下,会有非常多的跟UI相关的case,这样就会造成View的接口会很庞大。而MVVM就解决了这个问题,通过双向绑定的机制,实现数据和UI内容,只要想改其中一方,另一方都能够及时更新的一种设计理念,这样就省去了很多在View层中写很多case的情况,只需要改变数据就行。
在MVP中View和presenter要相互持有,方便调用对方,而在MVVM中View和ViewModel通过Binding进行关联,他们之间的关联处理通过DataBinding完成。
notion image

MVVM与DataBinding的关系

一句话表述就是,MVVM是一种思想,DataBinding是谷歌推出的方便实现MVVM的工具。在google推出DataBinding之前,因为xml layout功能较弱,想实现MVVM非常困难。而DataBinding的出现可以让我们很方便的实现MVVM。

3.2 DataBinding简介

DataBinding是实现视图和数据双向绑定的工具,这里简单介绍下基本用法,详细用法可以参照官方:https://developer.android.com/topic/libraries/data-binding/ 启用DataBinding,只需要在gradle文件中添加如下代码:
通过DataBindingUtil可以动态生成一个ViewDataBinding的子类,类名以layout文件名大写加Binding组成,如:
在layout中需要我们配置,每个控件绑定的实体对象,以layout进行包裹,data中配置变量名和类型,通过@{}或@{}的方式进行引用,其中@={}的方式表示双向绑定
为了实现双向绑定还需要对数据实体类做处理,继承BaseObservable,对读写方法做@Bindable和notifyPropertyChanged处理。还可以直接使用官方提供的泛型可观察对象 ObservableField,比如: private ObservableField name=new ObservableField<>();

3.3 代码结构

MVVM中跟MVP中一样,将三层划分的很清楚,Activity和xml layout充当View,ViewModel处理业务逻辑以及获取数据,弱化Model。 很多代码跟前面类似,这里只列出核心代码.
ViewMode层主要处理业务逻辑和获取数据,mViewDataBinding是通过View层传递过来。
View层实现
xml layout代码在上面介绍databing的用法时已给出,通过上面代码我们就将数据UserInfo跟View进行绑定了。比如我们更新用户信息,可以直接对View上的属性进行修改: mSampleViewModel.mViewDataBinding.tvName.setText("rose"); 也可以通过修改UserInfo实体类的字段信息: mSampleViewModel.mViewDataBinding.setUser(userInfo);
从此告别MVP中View层好多接口的问题,让View变得更简洁,修改任何一方,两者都会保持数据同步。

3.4 总结

看起来MVVM很好的解决了MVC和MVP的不足,但是由于数据和视图的双向绑定,导致出现问题时不太好定位来源,有可能数据问题导致,也有可能业务逻辑中对视图属性的修改导致。如果项目中打算用MVVM的话可以考虑使用官方的架构组件ViewModel、LiveData、DataBinding去实现MVVM
 

4 如何选择

 
如果项目简单,没什么复杂性,未来改动也不大的话,那就不要用设计模式或者架构方法,只需要将每个模块封装好,方便调用即可,不要为了使用设计模式或架构方法而使用。
对于偏向展示型的app,绝大多数业务逻辑都在后端,app主要功能就是展示数据,交互等,建议使用mvvm。对于工具类或者需要写很多业务逻辑app,使用mvp或者mvvm都可。如果想通过一个项目去学习架构和设计模式,建议用MVC然后在此基础上慢慢挖掘改进。最后你可能发现,改进的最终结果可能就变成了mvp,mvvm。
 

5 区别及优缺点

Presenter与ViewModel的区别 在MVP中,Presenter负责处理所有的视图逻辑。它直接与View交互,将Model的数据传递给View,调用View的方法更新UI。
而在MVVM中,ViewModel不直接引用View,而是通过数据绑定或观察者模式与View交互。ViewModel不需要关心View的生命周期,ViewModel的生命周期与View的生命周期解耦。此外ViewModel可以在不同的Activity和Fragment之间共享数据。
View角色的区别
在MVP中,View有一个对Presenter的引用,当用户操作UI时,View会直接调用Presenter的方法。而在MVVM中,View不需要知道ViewModel的存在,ViewModel只需要暴露出可观察的数据对象,View只需要观察这些数据对象并更新UI。
MVP的优点:
  • 结构清晰:每个组件都有明确的角色,使得代码更易于理解和维护。
  • 解耦:Presenter作为中介,将View和Model解耦,使得代码更易于测试。
MVP的缺点:
  • Presenter可能会变得过于复杂:因为所有的视图逻辑都在Presenter中处理,所以Presenter可能会变得非常大和复杂。
  • 生命周期管理复杂:Presenter需要处理View的生命周期,以防止内存泄漏。
MVVM的优点:
  • 解耦:View不直接与Model交互,而是通过ViewModel,这使得View和Model之间的依赖性降低,更易于测试和维护。
  • 支持数据绑定:使用MVVM,可以轻松实现View和ViewModel之间的数据绑定,当ViewModel中的数据改变时,UI会自动更新。
  • 生命周期管理简化:ViewModel的生命周期是与View的生命周期解耦的,即使在配置更改(例如屏幕旋转)导致View被销毁和重新创建,ViewModel的实例也会保留下来。
MVVM的缺点:
  • 对于简单的项目,MVVM可能会引入不必要的复杂性。
  • 如果没有正确地实现,可能会导致ViewModel和View之间的紧密耦合,这会使得代码难以维护和测试。

📎 参考文章

模块化&组件化&ARouterMVVM前置(1)——LifeCycle
LuluNotion
LuluNotion
一个普通的干饭人🍚
公告
type
status
date
slug
summary
tags
category
icon
password
🎉NotionNext 4.0即将到来🎉
-- 感谢您的支持 ---
👏欢迎更新体验👏