了解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 // 定义数据库信息,表信息,数据库版本



版权声明:本文为博主原创文章,转载请点赞此文并注明出处,谢谢!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容