安卓架构模式

文章对比了Android开发中的常见架构模式,包括MVC、MVP、MVVM和MVI,分析了各自的优缺点。MVC和MVP旨在分离表现逻辑和业务逻辑,但存在耦合问题。MVVM引入数据绑定,降低了交互复杂性,而MVI则强调单向数据流和响应式编程,提高了状态管理的清晰度。每种模式都有其适用场景,选择合适的架构对于项目的维护和扩展至关重要。
摘要由CSDN通过智能技术生成

安卓架构模式

MVC

MVC是安卓默认的模式。

分为3个部分:

  • View: Layout XML文件。
  • Model: 负责管理业务数据逻辑,如网络请求、数据库处理。
  • Controller: Activity负责处理表现逻辑。

MVC 初步解决了 Activity 代码太多的问题,但也有缺点:我们的初衷 Activity / Fragment 是只处理表现逻辑的部分 ,但现实是 Activity 天然不可避免要处理 UI,也要处理用户交互,说明 Activity 本身天然承担了 View 的角色。那么这个架构就会造成 Activity 里糅合了视图和业务的代码,分离程度不够。

在这里插入图片描述
优点:

mvc相对一个文件打天下,分离了Model和Controller,一定程度上实现了代码分离,降低代码的耦合性。

缺点:

1.Controller和View难以完全解耦(Activity即是控制器,又承担了视图层的工作)。
2.Controller权力大、太过臃肿,activity越改会变得越来越大。

MVP

和MVC区别:

1、Model和View不再进行直接通信,而是通过中间层Presenter来实现。
2、Acitivity功能被简化,不用再充当控制器,主要负责View层工作。

为了将 Activity 中的表现逻辑彻底分离出来,业界提出了 MVP 的设计。MVP 同样将代码划分为三个部分:

  • View: Activity 和 Layout XML 文件。
  • Model: 负责管理业务数据逻辑,如网络请求、数据库处理。
  • Presenter: 负责处理表现逻辑。

在实现细节上,View 和 Presenter 中间会定义一个协议接口 Contract,这个接口会约定 View 如何向 Presenter 发指令和 Presenter 如何 Callback 给 View。这样的架构里 Activity 不再有表现逻辑的部分,Activity 作为 View 的角色只处理和 UI 有关的事情。但还是存在一些缺点:

  • 双向依赖: View 和 Presenter 是双向依赖的,一旦 View 层做出改变,相应地 Presenter 也需要做出调整。在业务语境下,View 层变化是大概率事件;
  • 内存泄漏风险: Presenter 持有 View 层的引用,当用户关闭了 View 层,但 Model 层仍然在进行耗时操作,就会有内存泄漏风险。虽然有解决办法,但还是存在风险点和复杂度(弱引用 / onDestroy() 回收 Presenter)。
  • 协议接口类膨胀: View 层和 Presenter 层的交互需要定义接口方法,当交互非常复杂时,需要定义很多接口方法和回调方法,也不好维护。
    在这里插入图片描述

优点:

1、解决了MVC中Controller和View过度耦合的缺点,职责划分明确,更利于维护。
2、activity只剩下了view,presenter承担了view和model之间的交互,满足了单一职责原则,视图数据逻辑是清晰的。
V层对应Activity,只负责UI的展示和P层直接通信,和M层没有任何交互。
V层没有和M层有交互,可以抽成单独的组件,方便复用。
代码结构清晰,P层可以用于多个视图,而不需要改变P层的逻辑。
V层和M层完全分离,方便协同工作,只需要专注做视图或者逻辑控制部分,不用关系对方的逻辑。比如负责逻辑控制部分不用等设计出图,就可以直接写代码,并进行单元测试。
代码复用率高,方便单元测试。

缺点:

1、当项目越来越复杂时,接口数量变多,Presenter层也将变得越来越臃肿。
2、引入了interface,方法增多,增加一个方法要改几个地方;哪里有压迫哪里就有反抗。
M层和V层都需要和P层进行通许,会导致P层代码很复杂,而且都是通过接口通讯,如果一个P层用于多个Activity,所有Activity都要实现全部都接口,无论能不能用得到。修改P层接口,往往会涉及到很多个界面,很麻烦。
P层和V层通过接口通讯,会持有View的引用,容易造成内存泄露。
随着业务增多,P层即使只对应一个视图,接口也会越来越多。

MVVM

MVVM是Model、View、ViewModel的简写,在MVP基础上实现了数据视图的绑定(DataBinding),当数据发生变化时,视图会自动更新;反之,视图被改变时,数据也自动更新。

MVVM 模式改动在于中间的 Presenter 改为 ViewModel,MVVM 同样将代码划分为三个部分:

  • View: Activity 和 Layout XML 文件,与 MVP 中 View 的概念相同;
  • Model: 负责管理业务数据逻辑,如网络请求、数据库处理,与 MVP 中 Model 的概念相同;
  • ViewModel: 存储视图状态,负责处理表现逻辑,并将数据设置给可观察数据容器。

在实现细节上,View 和 Presenter 从双向依赖变成 View 可以向 ViewModel 发指令,但 ViewModel 不会直接向 View 回调,而是让 View 通过观察者的模式去监听数据的变化,有效规避了 MVP 双向依赖的缺点。但 MVVM 本身也存在一些缺点:

  • 多数据流: View 与 ViewModel 的交互分散,缺少唯一修改源,不易于追踪;
  • LiveData 膨胀: 复杂的页面需要定义多个 MutableLiveData,并且都需要暴露为不可变的 LiveData。
    在这里插入图片描述

DataBinding、ViewModel 和 LiveData 等组件是 Google 为了帮助我们实现 MVVM 模式提供的架构组件,它们并不是 MVVM 的本质,只是实现上的工具。

  • Lifecycle: 生命周期状态回调;
  • LiveData: 可观察的数据存储类;
  • databinding: 可以自动同步 UI 和 data,不用再 findviewById();
  • ViewModel: 存储界面相关的数据,这些数据不会在手机旋转等配置改变时丢失。

优点:

1、减少了接口数量
2、告别了繁琐的findbyid操作。
进一步解耦,ViewModel不持有View的引用,当V层改遍,只要V层绑定的数据不变,ViewModel就不需要修改。
不需要写很多样板代码,省略findViewById(),Activity变得很简介。
通过DataBinding实现View和Model的实时改变,一方改变就会同步到对方。

缺点: 在大型工程中,总结会遇到如下问题:

1、滥用LiveData造成系统内存管理负担,我们都知道LiveData是谷歌官网提供的,在没有LiveData之前MVP强调对象用完及时释放,LiveData生命期很长;
2、业务复杂时LiveData和View相互依赖,导致View和ViewModel职责不清晰,这就要求开发人员遵循规范编写业务逻辑清晰,否则别人接手难度大;
3、Xml和代码耦合,不方便业务迁移;
4、DataBinding的使用增加了编译一定耗时,它在使用过程中中还是不是会出问题。
DataBinding双向绑定采用异步更新数据,对ListView这样的列表,效率比较低。而且在实际开发中,设计出的Ui效果比较复杂,数据绑定不能完全实现,往往只使用到DataBinding一半的功能,数据更新部分还是手动实现。
DataBinding会自动生成大量的代码和属性字段。
复杂的页面要定义多个LiveData,并且都要暴露为不可变的LiveData。
LiveData是粘性事件,数据倒灌等问题。解决方法:使用第三方 UnPeekLiveData。

MVI

MVI 模式的改动在于将 View 和 ViewModel 之间的多数据流改为基于 ViewState 的单数据流。MVI 将代码分为以下四个部分:

  • View: Activity 和 Layout XML 文件,与 MVVM 中 View 的概念相同;
  • Intent: 定义数据操作,是将数据传到 Model 的唯一来源,相比 MVVM 是新的概念;
  • ViewModel: 存储视图状态,负责处理表现逻辑,并将 ViewState 设置给可观察数据容器;
  • ViewState: 一个数据类,包含页面状态和对应的数据。

在实现细节上,View 和 ViewModel 之间的多个交互(多 LiveData 数据流)变成了单数据流。无论 View 有多少个视图状态,只需要订阅一个 ViewState 便可以获取所有状态,再根据 ViewState 去响应。当然,实践中应该根据状态之间的关联程度来决定数据流的个数,不应该为了使用 MVI 模式而强行将多个无关的状态压缩在同一个数据流中。

  • 唯一可信源: 数据只有一个来源(ViewModel),与 MVVM 的思想相同;
  • 单数据流: View 和 ViewModel 之间只有一个数据流,只有一个地方可以修改数据,确保数据是安全稳定的。并且 View 只需要订阅一个 ViewState 就可以获取所有状态和数据,相比 MVVM 是新的特性;
  • 响应式: ViewState 包含页面当前的状态和数据,View 通过订阅 ViewState 就可以完成页面刷新,相比于 MVVM 是新的特性。

但 MVI 本身也存在一些缺点:

  • State 膨胀: 所有视图变化都转换为 ViewState,还需要管理不同状态下对应的数据。实践中应该根据状态之间的关联程度来决定使用单流还是多流;
  • 内存开销: ViewState 是不可变类,状态变更时需要创建新的对象,存在一定内存开销;
  • 局部刷新: View 根据 ViewState 响应,不易实现局部 Diff 刷新,可以使用 Flow#distinctUntilChanged() 来刷新来减少不必要的刷新。

不过,MVI 并不是一个全新的设计模式,其背后设计理念与 Redux 模式如出一辙。

View - View
Action - Intent
Store - ViewModel
State - ViewState
Reducer - Model

在这里插入图片描述
优点:

1.数据单向流动,容易对状态变化进行跟踪和回溯,可以把UI一次展示理解为单个State一次渲染
2.使用ViewState对State集中管理,只需订阅一个ViewState就可以获得页面所有状态。迫使程序员更全面的思考,将复用数据利用到最大。
3.更高效的性能,采用单向通信,可以获得更清晰严谨的代码,降低维护成本和测试难度。
UI的所有变化来自State,所以只需聚焦State,架构更简单、易于调试。
数据单向流动,很容易对状态变化进行跟踪和回溯。
State实例都是不可变的,确保线程安全。
UI只是反应State的变化,没有额外逻辑,可以被轻松替换或复用。

缺点:

1.所有的操作最终都会转换成State,所以当复杂页面的State容易膨胀。
2.State是不变的,每当State需要更新时都要创建新对象替代老对象,这会带来一定内存开销。

总结

类型创建过程A/F特点缺点建议
MVCC->M+VC分离了Model和ControllerControllder变复杂适用简单、修改少的页面
MVPV->P->MV在MVC基础通过接口分离View和ModelP和V的交互变得琐碎复杂核心、复杂、需求变更快的页面
MVVMV->VM ->MV在MVP基础上增加DataBinding,代码量更小XML和代码耦合核心、复杂、需求变更快的页面
MVIV->VM ->MV解决MVVM存在问题,将用户意图和UIstate分离有一定学习成本核心、复杂、需求变更快的页面

MVVM 和 MVP 的思想是相同的,最本质的概念就是 Activity 里做的事情太多了,所以要把 Activity 中与 UI 无关的部分抽离出来,交给别人做。这个 “别人” 在 MVP 里叫作 Presenter,在 MVVM 里叫作 ViewModel。而不论是 MVP 中的约定接口,还是 ViewModel 里的观察者模式,这些都是实现上的细节而已。

MVI 与前者的主要区别不在于强调严格的单向数据流,而在于从命令式的开发模式,转变为响应式的开发模式。我们并不是说越新潮,越复杂的架构就是最好的,只有合适的架构才是最好的。但是不可否认,从 React 到 Flutter,从 MVI 到 Compose,响应式编程似乎有一统天下的趋势。未来会怎么样,我们拭目以待。

转载至:
作者:彭旭锐
链接:Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
来源:掘金
作者:不会画板子的物联网工程师
链接:Android~MVC、MVP、MVVM和MVI对比
来源:CSDN

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值