文 | 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 // 定义数据库信息,表信息,数据库版本
版权声明:本文为博主原创文章,转载请点赞此文并注明出处,谢谢!