Android MVC、MVP、MVVM架构模式

MVC架构模式

这里写图片描述
主要模块:
1 View:对应于xml布局文件和java代码动态view部分
2 Model:主要负责网络请求,数据库处理,I/O的操作,即页面的数据来源
3 Controller:主要负责业务逻辑,在android中由Activity承担,同时因为XML视图功能太弱,所以Activity既要负责视图的显示又要加入控制逻辑,承担的功能过多

流程:
圈1 用户操作,传送指令到Controller
圈2 Controller完成逻辑处理,对Model的数据进行修改
圈3 model将修改了的数据再传给View
圈4 也可以直接命令Controller

优点: 简单,android应用层开发天然默认就是MVC架构
缺点:
1.Activity同时负责View与Controller层的工作,违背了单一职责原则,当Activity有较复杂的功能实现时,Activity会很臃肿,代码会很混乱
2. Model层与View层存在耦合,互相依赖,违背了迪米特法则


MVP架构模式

这里写图片描述
主要模块:
1 View:对应于XML,Activity,Fragment,Adapter等,只负责显示UI,只与Presenter层交互,与Model层没有耦合,View不部署任何业务逻辑
1.5 View Interface :View持有presenter,Presenter通过View Interface与View交互,降低耦合,单元测试的时候,可以不需要部署到真机或者模拟器测试,只需要通过interface模拟Activity对Presenter进行测试。
2 Presenter:处理所有的业务逻辑
4 Model:主要负责网络请求,数据库处理,I/O的操作,即页面的数据来源

优点:
1 (与MVC的Controller区别)在Android的Activity中,不仅承担了View的角色,还承担了一部分的Controller角色。导致代码臃肿。而MVP的Presenter能把Activity中的UI逻辑抽象成View接口,把业务逻辑抽象成Presenter接口,业务逻辑放在Presenter实现。并且通过Presenter这个桥梁,View不能直接和Model进行互操作。 View是Passive View模式,被动显示数据的界面,而Presenter是主动的
2 可以将Presenter用于多个View,增加灵活性
3 方便进行单元测试 可以写一个PresenterTest的实现类继承Presenter的接口,现在只要在Activity里把Presenter的创建换成PresenterTest,就能进行单元测试

缺点:
1 Activity需要实现各种跟UI相关的接口,同时要在Activity中编写大量的事件,然后在事件处理中调用presenter的业务处理方法,View和Presenter只是互相持有引用并互相做回调,代码不美观。
2 这种模式中,程序的主角是UI,通过UI事件的触发对数据进行处理,更新UI就要考虑线程的问题。而且UI改变后牵扯的逻辑耦合度太高,一旦控件更改(比如TextView 替换 EditText等)牵扯的更新UI的接口就必须得换。
3 复杂的业务还是会导致View的接口多,presenter层臃肿的问题。


MVVM架构模式

这里写图片描述


这里写图片描述
主要模块:
1 View:XML,Activity,Fragment,Adapter等 View不部署任何业务逻辑
不写和业务逻辑相关代码,也不写需要根据业务逻辑来更新UI的代码,因为更新UI通过DataBinding实现,更新UI在ViewModel里面做
Activity 要做的事就是初始化一些控件和更新一些与事务逻辑无关的UI更新(点击变色,滑动渐变,RecyclerView的分隔线设置等)

2 ViewModel:处理所有的业务逻辑
通过DataBinding 框架双向绑定,将数据在相应的控件上会自动去更改UI,也可以将View的变动自动反馈给ViewModel层进行操作。
一般包括:

  • Context (上下文)
    1 做网络请求我们必须把Retrofit Service返回的Observable绑定到Context的生命周期上,防止在请求回来时Activity已经销毁等异常,其实这个Context的目的就是把网络请求绑定到当前页面的生命周期中
    2 两个ViewModel 之间的联系是通过Messenger来做,这个Messenger 是需要用到Context

  • Model (数据模型Bean)
    把数据映射到View中可能需要大量对Model的数据拷贝,拿Model 的字段去生成对应的ObservableField(我们不会直接拿Model的数据去做展示),这里其实是有必要在一个ViewModel 保留原始的Model引用

  • Data Field (数据绑定)

  • Command (命令绑定)

  • Child ViewModel (子ViewModel)
    ViewModel 是以业务划分的,若你一个Activity里面有两个Fragment,并且两个Fragment做的业务不一样,因此由两个ViewModel来处理。Activity 本身可能就有个ViewModel 来做它自己的业务,这时候Activity的这个ViewModel里面可能包含了两个Fragment分别的ViewModel

3 Model:主要负责网络请求,数据库处理,I/O的操作,即页面的数据来源
实体模型(Bean)
Retrofit 的Service
ViewModel 可以根据Model 获取一个Bean的Observable( RxJava ),然后做一些数据转换操作和映射到ViewModel 中的一些字段,最后把这些字段绑定到View层上

主要流程:
圈1+圈2:
数据绑定,命令绑定
ViewModel和View之间通过data-binding双向绑定,当其中之一变动,另一个会自动反映。降低耦合性
MVVM Light Toolkit 也完善了一些data-binding框架不足之处

圈3 vm直接调用model层
圈4 model层通过EventBus方式抛给需要的vm,vm设置监听

优点:
和MVP的区别: 不用去主动去刷新UI了,只要Model数据变了,会自动反映到UI上。换句话说,MVVM更像是自动化的MVP,代码使用上MVVM更强调的是数据,数据来驱动,而MVP更偏向于是动作。

  • 解决 MVP 中 View 的接口爆炸问题。
  • ViewModel 不持有 View 层引用,解决双向依赖问题

缺点:
1 为保证对外暴露的LiveData是不可变的,需要一个可变的和一个不可变的,存在数据转化处理,需要添加不少模板代码并且容易遗忘
2 View层与ViewModel层的交互比较分散零乱,不成体系(可以用IDL,但是IDL也臃肿而且难维护更新)
3 DataBinding不好用,较复杂,并且数据难跟踪和回溯

不使用dataBinding的MVVM:
View观察ViewModle的数据变化并自我更新(如android原生开发使用View通过LiveData等观察ViewModle的数据变化并自我更新,C++跨平台方式通过IDL方式进行监听ViewModel的数据变化),这其实是单一数据源而不是双向数据绑定,所以其实MVVM的这一特性没有使用,View通过调用ViewModel提供的方法来与ViewMdoel交互


MVI

在这里插入图片描述主要模块:
View XML,Activity,Fragment,Adapter等 View不部署任何业务逻辑 MVI中的View通过订阅Model的变化实现界面刷新
Model: MVI的Model主要指UI状态(State)
Intent 用户的任何操作都被包装成Intent后发送给Model层进行数据请求

主要流程:
用户操作以Intent的形式通知Model
Model基于Intent更新State
View接收到State变化刷新UI

在这里插入图片描述

使用ViewModel来承载MVI的Model层,总体结构也与MVVM类似,主要区别在于Model与View层交互的部分
Model层承载UI状态,并暴露出ViewState供View订阅,ViewState是个data class,包含所有页面状态
View层通过Action更新ViewState,替代MVVM通过调用ViewModel方法交互的方式

优点:(和MVVM的区别:)
1 (没有DataBinding)强调数据单向流动,很容易对状态变化进行跟踪和回溯
2 使用ViewState对State集中管理,只需要订阅一个 ViewState 便可获取页面的所有状态,只需聚焦State,架构更简单,相对 MVVM 减少了不少模板代码
3 MVVM的VM之间难以调用,如android原生的方式,需要通过VM1传递到View1到View2再到VM2,而MVI通过树形结构向上回溯ability

缺点:
1 所有的操作最终都会转换成State,所以当复杂页面的State容易膨胀
解决:可以根据界面实际状态的独立性,选择定义多个ViewState。
2 state实例都是不可变的,确保线程安全,但是每当state需要更新时都要创建新对象替代老对象,这会带来一定内存开销
3. ViewState 对象中的字段越多,数据流就越有可能因为其中一个字段被更新而发出。
解决:使用diff机制来解决多次数据更新时的有效性,实现局部刷新,比如使用distinctUntilChanged() 函数等


C++跨平台 会遇到接口膨胀问题

解决:用MVVM 字符串上抛下调

MVVM VM到V的一种类似前后端对接,MVVM通过bind/handle方式,通过key value 进行解耦,DataBinding或者IDL方式进行接口约束

DataBinding主要是xml中的属性变更通过Activity到VM再到Model层,
对model和XML的属性进行了绑定,通过数据驱动直接改UI
(但是这种只适用于Android,并且其实挺臃肿的,UI代码层还需要和XML层做一套绑定)
而IDL的方式是跨平台,并且只到UI层,UI层直接通过代码的方式改UI即可

1 在MVVM中,数据和业务逻辑处于一个独立的ViewModel中,ViewModel只要关注数据和业务逻辑,不需要和UI或者控件打交道。由数据自动去驱动UI去自动更新UI,UI的改变又同时自动反馈到数据,数据成为主导因素,这样使得在业务逻辑处理只要关心数据

2 一个View Model复用到多个View中,同样的一份数据,用不同的UI去做展示,对于版本迭代频繁的UI改动,只要更换View层就行

3 上层别做持久层(变量,数据)而是放到model去,vm可以做暂存,上层也尽量别起线程,这样各端都要创建线程,而且线程不好统一管理,会混乱

缺点: 因为各层解耦,较难上手,排查问题也会稍微慢一些,通过字符串的上抛下调形式连接View和VM,不如接口直观,调试起来也较难。

优点: 对于那种重跨平台的,重C++的,上层UI会很薄,而且UI是被动的,再引入一个新的UI(如后面引入了Flutter、QT)也是很简单,只用对接好接口,贴一层皮即可。


idl 接口描述语言

一般用于约束接口 并且对接口进行描述的
如AIDL 通过.aidl文件 可以自动生成相应的.java文件

原理:mvvm中,对view和viewModel的交互通过IDL进行key的约束(将上抛和下调的key以及数据结构体做约束)
idl文件编译后,会生成r_view_model.h头文件
优点:自动化生成了各种常量(避免书写错误) 代码中直接调用常量


参考文献:
https://www.tianmaying.com/tutorial/AndroidMVC
http://www.jianshu.com/p/2fc41a310f79
https://juejin.cn/post/7022624191723601928

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android开发中,MVPMVVM是两种常用的架构模式MVP(Model-View-Presenter)模式中,View负责展示数据和处理用户交互,Model负责数据的获取和处理,Presenter作为中间人连接View和Model,负责处理业务逻辑。MVP模式通过Presenter来解决View和Model的直接通信,提高了代码的复用性、可拓展性和降低了耦合度。但是,MVP模式会增加很多接口和实现类,代码量相对较大,适用于中小型项目,不太适合大型项目。\[2\] MVVM(Model-View-ViewModel)模式是在MVP的基础上进一步发展和规范的。MVVM模式中,ViewModel负责处理业务逻辑和数据的获取,View负责展示数据和处理用户交互,Model负责数据的存储和处理。MVVM模式引入了Data Binding的概念,通过Binding来实现View接口的实现方法,使代码更加优雅简洁。MVVM模式相对于MVP模式更加灵活和方便测试。\[3\] 所以,MVPMVVM都是为了解决MVC模式中代码臃肿、耦合度高等问题而提出的。MVP通过Presenter来解决View和Model的直接通信,而MVVM通过Data Binding来实现View接口的实现方法,使代码更加优雅简洁。在Android开发中,根据项目的规模和需求选择适合的架构模式是很重要的。 #### 引用[.reference_title] - *1* [一篇文章讲清楚Android中的MVCMVPMVVM架构 (附实现代码)](https://blog.csdn.net/bugyinyin/article/details/128932821)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Android的三种开发模式 mvc mvp mvvm](https://blog.csdn.net/qq_43649223/article/details/120746596)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值