了解MVC、MVP、MVVM、AAC等App架构模式

文 | Promise Sun


 

注:本文是个人经过学习之后,所做的一篇简单的笔记,并不涉及理论分析,仅供快速记忆时参考。)

一、MVC:

M——对应Model,代表业务数据

V——对应View,代表视图

C——对应Controller,代表控制器

MVC架构将视图和数据分离。在MVC模型里,Model不依赖于View,但是View是依赖于Model的。

 

优点MVC 分层有助于管理复杂的应用程序;简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。对于开发大型软件来说更方便进行模块的划分,提高编码速度与质量。

缺点:有一些业务逻辑在View里实现,导致要更改View比较困难,至少那些业务逻辑是无法重用的。

 

二、MVP

MVP是基于MVC的。将MVC进行升级,对应Android开发中就是帮助Activity解压。

mvp非常适合大型的APP开发。

M——(Model) 数据相关层,负责提供数据

V——(View) 视图层,负责显示。eg:Activity上的布局

P——(Presenter) 纽带层,用来连接Model与View。负责逻辑的处理

Note:

Model层是真正处理数据的,Presenter是联系M和V的中介,P持有M和V的引用,P和V是双向引用。

Model是一个独立于Activity/Framgment用于保存数据的类。因为它是独立于系统组件的,因此,不受系统生命周期的的影响。

 

核心:

把数据和业务逻辑从视图层(View)剥离出来,V和P通过接口回调来通信。

 

优点:

1)可以进行View的模拟测试。

MVP模式很适合测试,单独测试VIEW成了一种可能。我们可以模拟View和Model的数据来测试Presenter的逻辑。

2)View与Model完全隔离

Model和View之间具有良好的松耦合设计,也就是说,如果Model或View中的一方发生变化,只要交互接口不变,另一方就没必要对上述变化做出改变。使得Model层的业务逻辑具有很好的灵活性和可重用性。

这种分层思想在一定程度实现了解耦,符合类的单一职责设计原则。

3)Presenter与View的具体实现技术无关

应用程序可以用同一个Model层适配多种技术构建的View层。

Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以保持Presenter的不变,即重用

 

缺点:

1)增加了代码的复杂度,特别是针对小型Android应用的开发,会使程序冗余。Presenter中除了应用逻辑以外,还有大量的View->Model,Model->View的手动同步逻辑,会导致Presenter臃肿,维护困难。

2)内存泄漏和空指针问题。由于P和V是互相引用,如果页面销毁时P还有正在进行的任务,那Activity无法回收,就发生了内存泄漏。

解决思路:在onDestroy()断开引用关系,并取消网络任务。也可以通过弱引用来解决。)

3)P和V需要通过接口交互,还是存在一定耦合,算不上真正的解耦;如果接口有所变化的时候,需要改动的地方太多;

 

MVC与MVP的不同:

1)MVP中Presenter取代了MVC中的Controller

2)MVC中Model、View、Controller之间相互发生通信,而MVP中Model与Presenter相互通信,View与Presenter相互通信,而Model与View之间没有通信。

3)MVC中Activity同时充当了V和C的角色,这就属于界限划分不清楚。而MVP则划分的很清楚,Activity只充当V的角色,业务逻辑控制交给了Presenter.

4)在MVP中View并不直接使用Model,它们之间的通信是通过Presenter(MVC中的Controller)来进行的,所有的交互都发生在Presenter内部而在MVC中View会直接从Model中读取数据而不是通过Controller。

 

三、MVVM

MVVM:Model–View–Viewmodel

(参考网址:https://www.jianshu.com/p/3651917c9b38)

是一种软件架构模式。是MVP的升级版。MVVM各个层职责单一,结构清晰,应用可以很方便地进行测试、维护和扩展。

M——Model层数据模型(从服务器拉回来的JSON数据)。主要负责数据的提供。

V——View层,视图展示。View层是可以持有ViewModel的。

VM——ViewModel层,主要负责业务逻辑的处理。ViewModel层不涉及任何的视图操作。ViewModel层不持有View层的引用。这样进一步降低了耦合,View层代码的改变不会影响到ViewModel层。

 

1)MVVM和MVP区别是vm和v是单向引用,只有activity持有vm引用,vm是不持有view的引用的,所以vm的构造方法中不能传入视图相关的对象。这样做,是为了防止生命周期问题导致的内存泄漏。

2)MVVM解决了MVP中接口繁杂、内存泄漏等疑难杂症。

3)结合Jetpack相关组件,MVVM效果会更好。

4)数据驱动。在常规的开发模式中,数据变化需要更新UI的时候,需要先获取UI控件的引用,然后再更新UI。获取用户的输入和操作也需要通过UI控件的引用。在MVVM中,这些都是通过数据驱动来自动完成的,数据变化后会自动更新UI,UI的改变也能自动反馈到数据层,数据成为主导因素。这样MVVM层在业务逻辑处理中只要关心数据,不需要直接和UI打交道,在业务处理过程中简单方便很多。

Note:

DataBinding是一个实现数据和UI绑定的框架,只是构建MVVM模式的一个工具。

MVVM可以根据项目的实际业务情况,结合AAC一起使用,效果会更好。

 

(注:以下为MVVM的故事,只做了解即可)

MVVM其实分为2个阶段:在2017之前,是基于databinding的,在2017之后是基于AAC架构的,也就是livedata、viewmodel相关。由于在2016、2017年Jetpack相关的Viewmodel、LiveData还没有推广开,在2017之前要把数据从vm传给v是比较麻烦,不用接口回调的话,用观察者模式来做是比较方便的,但是那时候livedata还没有出来,就只能用databinding的观察者模式或自己手写观察者,由于这样做比较麻烦,很多人甚至直接沿用接口回调去更新UI数据。正是由于当时的技术和认知不足以及很多误导博客的广泛传播,导致了一部分人以为MVP+databinding就是MVVM了,这是一种错误认知。

 

四、AAC

AAC(全称 Android Architecture Components)是谷歌在Google I/O 2017发布一套帮助开发者解决Android架构设计的方案。里面包含了两大块内容:

1)生命周期相关的Lifecycle-aware Components

2)数据库解决方案Room

 

优点:

使用 Android Architecture Components 提供的组件简化我们的开发,能够使我们开发的应用模块更解耦更稳定,视图与数据持久层分离,以及更好的扩展性与灵活性。

 

提供的主要组件:

Lifecycle:管理组件生命周期

指的是 android.arch.lifecycle 包下提供的各种类与接口,可以让开发者构建能感知其他组件(主要指Activity 、Fragment)生命周期(lifecycle-aware)的类。

Lifecycle 使用两个主要的枚举类来表示其所关联组件的生命周期:

Event 事件:从组件或者Lifecycle类分发出来的生命周期,它们和Activity/Fragment生命周期的事件一一对应。(ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY);

State 状态:当前组件的生命周期状态(INITIALIZED, DESTROYED, CREATED, STARTED, RESUMED)。

 

Lifecycle的使用:

1)Lifecycle 提供的 LifecycleObserver,用以当 Activity 生命周期发生变化的时候主动通知需求方。提供的LifecycleRegistry 类用于注册和反注册需要观察当前组件生命周期的 Observer。

2)LiveData是一个包含可以被观察的数据载体,基于观察者模式实现。

LiveData能够感知组件(例如activities, fragments, services)的生命周期,防止内存泄漏。

LiveData能够在组件生命周期结束后自动阻断数据流的传播,防止产生空指针等意外。

3)ViewModel 与 LiveData 结合使用,可以实现多处 UI 自动更新。

 

Room: 持久化数据结构

Room 持久层库提供了一个方便我们访问 SQLite 数据库的抽象层(an abstraction layer ),帮助我们更好的在 APP 上创建我们的数据缓存,能够让 APP 即使在没有网络的情况也能正常使用

Note:

主要通过注解实现数据的增删改查。

数据查询可以返回 LiveData 数据,通过 query 查询返回的实体,可以封装成对应RxJava 的操作符封装对象,

 

使用到的主要注解:

@Entity(tableName = "orders") // 定义表名;

@PrimaryKey // 定义主键;

@ColumnInfo(name = "order_id") // 定义数据表中的字段名;

@Ignore // 指示 Room 需要忽略的字段或方法;

@Embedded  // 指定嵌入实体

@Query("SELECT * FROM orders") // 定义查询数据接口;

@Insert // 定义增加数据接口;

@Delete // 定义删除数据接口;

@Update // 定义更新数据接口;

@Database // 定义数据库信息,表信息,数据库版本

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值