1. 降低耦合度,实现了Model和View真正的完全分离,可以修改View而不影响Modle
2. 模块职责划分明显,层次清晰(下面会介绍Bob大叔的Clean Architecture)
3. 隐藏数据
4. Presenter可以复用,一个Presenter可以用于多个View,而不需要更改Presenter的逻辑(当然是在View的改动不影响业务逻辑的前提下)
5. 利于测试驱动开发。以前的Android开发是难以进行单元测试的(虽然很多Android开发者都没有写过测试用例,但是随着项目变得越来越复杂,没有测试是很难保证软件质量的;而且近几年来Android上的测试框架已经有了长足的发展——开始写测试用例吧),在使用MVP的项目中Presenter对View是通过接口进行,在对Presenter进行不依赖UI环境的单元测试的时候。可以通过Mock一个View对象,这个对象只需要实现了View的接口即可。然后依赖注入到Presenter中,单元测试的时候就可以完整的测试Presenter应用逻辑的正确性。
6. View可以进行组件化。在MVP当中,View不依赖Model。这样就可以让View从特定的业务场景中脱离出来,可以说View可以做到对业务完全无知。它只需要提供一系列接口提供给上层操作。这样就可以做到高度可复用的View组件。
7. 代码灵活性
缺点:
1. Presenter中除了应用逻辑以外,还有大量的View->Model,Model->View的手动同步逻辑,造成Presenter比较笨重,维护起来会比较困难。
2. 由于对视图的渲染放在了Presenter中,所以视图和Presenter的交互会过于频繁。
3. 如果Presenter过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密。一旦视图需要变更,那么Presenter也需要变更了。
4. 额外的代码复杂度及学习成本。
1.6. 小结
在MVP模式里通常包含4个要素:
(1) View :负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
(2) View interface :需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
(3) Model :负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
(4) Presenter :作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
�
二、MVX 剖析
2.1. M(Model)
模型:表示数据模型和业务逻辑(business logic)。模型并不总是DataSet,DataTable之类的东西,它代表着一类组件(components)或类(class),这些组件或类可以向外部提供数据,同时也能从外部获取数据并将这些数据存储在某个地方。简单的理解,可以把模型想象成“外观类(facade class)”。译注:这里的外观是指“外观模式”中所说的外观。外观的一般作用是为一个复杂的子系统提供高层次的简单易用的访问接口,可以参看下面的图来理解它的原理:
model层主要负责:
· 从网络,数据库,文件,传感器,第三方等数据源读写数据。
· 对外部的数据类型进行解析转换为APP内部数据交由上层处理。
· 对数据的临时存储,管理,协调上层数据请求。
2.2 V(View)
视图:将数据呈现给用户。一般的视图都只是包含用户界面(UI),而不包含界面逻辑。比如,Asp.net中包含控件的页面(page)就是一个视图。视图可以从模型中读取数据,但是不能修改或更新模型。
view 层主要负责:
· 提供UI交互
· 在presenter的控制下修改UI。
· 将业务事件交由presenter处理。
注意: View层不存储数据,不与Model层交互。
在Android中View层一般是Activity、Fragment、View(控件)、ViewGroup(布局等)等。
2.3. X(C-Controller、P-Presenter、VM-ViewModel)
控制器:View捕获到用户交互操作后会直接转发给Controller,后者完成相应的UI逻辑。如果需要涉及业务功能的调用,Controller会直接调用Model。在完成UI处理之后,Controller会根据需要控制原View或者创建新的View对用户交互操作予以响应。
层现器:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。Presenter包含了根据用户在视图中的行为去更新模型的逻辑。视图仅仅只是将用户的行为告知Presenter,而Presenter负责从视图中取得数据然后发送给模型。
视图模型:binder 所在之处,是 View 的抽象,对外暴露出公共属性和命令,它是View的抽象,负责View与Model之间信息转换,将View的Command传送到Model。ViewModel的含义就是 “Model of View”,视图的模型。它的含义包含了领域模型(Domain Model)和视图的状态(State)。可以简单把ViewModel理解为页面上所显示内容的数据抽象,和Domain Model不一样,ViewModel更适合用来描述View。
2.4. 小结
MVC模式、MVP模式和MVVM模式都作为用来分离UI层与业务层的一种开发模式。这些模式之间的差异可以归纳为对这个问题处理的方式的不同。
三、MVX 与三层架构
相信不少童鞋和我有过同样的疑惑:MVX分为了M-V-X三层,那这到底和软件的三层架构有何关系呢?我们带着问题继续往下阅读。
3.1. 什么是三层架构
三层架构是一个分层式的软件体系架构设计,它可适用于任何一个项目。通常意义上的三层架构就是将整个业务应用划分为:界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。区分层次的目的即为了“高内聚低耦合”的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层、业务逻辑层(又或称为领域层)、表示层。(参考自:百度百科)
常见的架构有:
· 分层架构(如:三层架构)
· 事件驱动架构
· 微内核架构
· 微服务架构
· 基于空间的架构
推荐阅读《软件架构模式》
3.2. 三层架构和 MVX 的关系
首先,我想说三层架构(分层架构)和 MVX 没有什么关系,它们不在同一个层次上(三层是一种架构思想,更多的是和事件驱动架构、微内核架构等放在一起讨论,而我更喜欢把 MVX 做为模式来对待)。
三层是从整个应用程序架构的角度来分为DAL(数据访问层)、BLL(业务逻辑层)、WEB层(界面层)各司其职,意在职责分离;三层是为了解决整个应用程序中各个业务操作过程中不同阶段的代码封装的问题,为了使程序员更加专注的处理某阶段的业务逻辑;并且三层只是多层架构中的一种情况,完全可以根据需要分为多层。
MVC 主要是为了解决应用程序用户界面的样式替换问题,把展示数据的 HTML 页面尽可能的和业务代码分离。MVC把纯净的界面展示逻辑(用户界面)独立到一些文件中(Views),把一些和用户交互的程序逻辑(Controller)单独放在一些文件中,在 Views 和 Controller 中传递数据使用一些专门封装数据的实体对象,这些对象,统称为Models。而在其后出现的 MVP 以及 MVVM 与 MVC 的作用类似,MVX 主要的区别在于如何解决 M 与 V 之间的连接与更新。
总之一句话,MVX 是一种模式,Spring MVC 以及 ASP.NET MVC 等是一个基于MVC模式的开发框架,三层架构是一种架构。
其次,它们都有一个表现层,但是这两者的展现层并不是一样的。可以这样看待 MVX 与三层架构中的表现层的关系,MVX 中的 V 和 X 都属于三层架构中的表现层,可以看下图的示意。
最后,虽然都有提到 Model,但是在 MVX 中没有把业务的逻辑访问看成两个层,这是采用三层架构或 MVX 搭建程序最主要的区别。在三层架构中Model 的概念与 MVX 中 Model 的概念是不一样的,“三层”中典型的Model 层是以实体类构成的,而MVC里,则是由业务逻辑与访问数据组成的。
也就是说,MVX 与三层架构说的根本不是一回事。在所谓的“三层”中,它要求你将BLL层独立出来,它只是告诉你表示层和业务逻辑层之间的静态关系。而 MVX 则告诉你在这个具体的地方如何处理其动态驱动流程,尽管 MVC 仍然粗糙(甚至 MVP、MVVM也是粗糙的),但是已经比所谓三层更细致一些了(三层是架构好吗…)。
四、Android 上 MVP 的几种实现
絮絮叨叨说了一大堆,终于干货要来了。正所谓:Talk is cheap,show me the code.下面会给出示例代码,请继续阅读。
在 Android 开发中讨论 MVP、MVVM 最终都离不了 Uncle Bob 的 The Clean Architecture。(请自行阅读,相信阅读原文会有更大的收获)
下面,我会尝试一一细数 Android 上常见的 MVP 实现方式(说明:并没有什么排序规则,只谈大家的实现思路,展示的顺序只是为了方便大家的理解和阅读)。
4.1. 存取用户信息的 MVP 小 Demo
这其实是我最先接触 MVP 时看到的示例,代码很少,但是把 MVP 的分层展示的挺清晰。
源码:GitHub 地址
4.2. 天气查询的 MVP 小 Demo
现在的 Andorid 开发怎么能够离开网络,来一个有网络的示例。该天气查询 Demo,是通过访问 Web 服务获取地区的天气信息(返回为JSON),然后在 Activity 中用 TextView 展示出来。
原文:Android中的MVP
源码:GitHub 地址
4.3. 使用 Activity/Fragment 作为 Presenter 的探索
上面的示例 View 都是 Activity 来承担的,Presenter 是一个普通的类,前面讨论过 Android 在不同场景下会进入不同的生命周期,这将可能导致 Presenter 也随着其生命周期需要做出响应。从这个角度考虑,有不少开发者提出了 MVP 实现的其他思路,接下来我们要探讨的就是使用 Activity/Fragment 作为 Presenter 的一些实现方案。
4.3.1 一种实现MVP模式的新思路
其中有使用 Activity 和 Fragment 作为 Presenters 和使用 Adapter作为 Presenter的探讨,思路挺有意思,可以去看看。
原文:android-mvp-an-alternate-approach
源码:GitHub 地址
4.3.2. TheMVP 介绍
TheMVP使用Activity作为Presenter层来处理代码逻辑,通过让Activity包含一个ViewDelegate对象来间接操作View层对外提供的方法,从而做到完全解耦视图层。
源码:GitHub 地址
4.3.3 MVPro 介绍
MVPro的实现很简单,思想和上面两篇文章(一种在android中实现MVP模式的新思路和用MVP架构开发Android应用)介绍的一样,都是将Activity和Fragment作为Presenter。Presenter即我们的Activity或者Fragment, View呢?说白了就是我们从Activity和Fragment中提取出来的和View操作相关的代码。
源码:GitHub 地址
4.4. Nucleus 框架
该框架还是值得一看的,作者 Konstantin Mikheev 对于 MVP 的理解挺有见地。
Nucleus is a simple Android library, which utilizes the Model-View-Presenter pattern to properly connect background tasks with visual parts of an application.
原文:Introduction to Model View Presenter on Android
译文:介绍ModelViewPresenter在Android中的应用
源码:GitHub 地址
4.5. Beam 框架
该框架的作者对 MVP 的理解的特点如下:
Activity会在很多情况下被系统重启:
当用户旋转屏幕
在后台时内存不足
改变语言设置
attache 一个外部显示器等。
正确的方式应该是:
**Presenter与Activity的绑定关系应由静态类管理。而不是由Activity管理。**当Activity意外重启时Presenter不应重启。Activity重启时,Presenter与Activity重新绑定,根据数据恢复Activity状态。
而当Activity真正销毁时。对应Presenter才应该跟随销毁。
这也是对 Presenter 管理的一个思路,可以参考。
源码:GitHub 地址
4.6. Mosby 框架
我给这篇关于Android库的博客起的名字灵感来源于《老爸老妈浪漫史》中的建筑设计师Ted Mosby。这个Mosby库可以帮助大家在Android上通过Model-View-Presenter模式做出一个完善稳健、可重复使用的软件,还可以借助ViewState轻松实现屏幕翻转。
这又是一种解决Activity/Fragment生命周期在屏幕翻转等场景下对Presenter的处理的思路。
原文:Ted Mosby – Software Architect
源码:GitHub 地址
4.7. Loader 的使用
就像刚才说的一样,关键问题就是在哪里存储Presenter以及什么时候销毁它们。而我们刚刚就看到了Loader的强大之处:由安卓系统框架提供,有单独生命周期,会被自动回收且不必在后台运行。
所以思考一下需求以及Loader的功能,我们可以让Loader作为Presenter的提供者,而不需要担心手机状态改变。
将同步的Loader作为存放Presenter的缓存。
这里的重点就在于同步使用Loader时,我们可以知道在生命周期的哪个阶段Presenter被创建了并且可以工作了。甚至是在Activity/Fragment可见之前。
使用Loader,思路很有新意,关键确实解决了问题,更关键的是使用的是 Android Framework 提供的功能。
原文:Presenter surviving orientation changes with Loaders
源码:GitHub 地址
4.8. Google 官方推荐
大 Boss 总是最后出场,对于 Android 上 MVP 的实现,Google 给也出了一些建议和实例,赶紧看看去吧。
原文:Android Architecture Blueprints [beta]
源码:GitHub 地址
4.9. MVP 实现的完整开源项目
4.9.1. Philm
ChrisBannes的开源项目Philm,其整体架构是一套MVP的实现。这里有一篇分析该项目的文章,可以直接去读源码,也可以先看看 lightSky 是怎么分析的。
Philm 分析:开源项目Philm的MVP架构分析
源码:GitHub 地址
4.9.2. 使用 Beam 开发的 APP
SearchPictureTool 搜图神器
Fishing 空钩钓鱼
Beam 前面已有介绍,感兴趣的童鞋可以看看上面两个项目。
4.9.3. 干货集中营客户端
干货集中营有不少的开源实现都是 MVP 模式的(下面的 App 是官网上列出来的,具体是否都采用了 MVP 本人没有一一查阅)。
4.10. 小结
上述众多解决方案都集中在 Presenter 实现的问题上,这主要是由于 Activity、Fragment 的复杂性导致的,它们有众多生命周期,它们无所不能,是否把它们仅仅视作 View 成了争论的焦点。个人认为从编码的难易程度和编码的习惯来说,我赞成把 Activity、Fragment 作为 View 即可,我们可以考虑其他方式来保证Presenter的生命周期和防止 Presenter 引起内存泄漏。其中使用 Loader 的方案就非常优雅,下面在本人的示例项目中也会采用这种方式。
关于 5 和 6 将在下篇中阐述,示例代码也会在下篇中给出。正所谓:Talk is cheap show me the code.
最后
题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多程序员朋友无法获得正确的资料得到学习提升,故此将并将重要的Android进阶资料包括自定义view、性能优化、MVC与MVP与MVVM三大框架的区别、NDK技术、阿里面试题精编汇总、常见源码分析等学习资料免费分享出来。
知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。包含知识脉络 + 诸多细节,由于篇幅有限,下面只是以图片的形式给大家展示一部分。
点击下面链接即可直接领取
【Android高级架构视频学习资源】
**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
【Android进阶学习视频】、【全套Android面试秘籍】可以简信我【学习】查看免费领取方式!
总结
可以看出,笔者的工作学习模式便是由以下 「六个要点」 组成:
❝ 多层次的工作/学习计划 + 番茄工作法 + 定额工作法 + 批处理 + 多任务并行 + 图层工作法❞
希望大家能将这些要点融入自己的工作学习当中,我相信一定会工作与学习地更富有成效。
下面是我学习用到的一些书籍学习导图,以及系统的学习资料。每一个知识点,都有对应的导图,学习的资料,视频,面试题目。
**如:我需要学习 **Flutter的知识。(大家可以参考我的学习方法)
- Flutter 的思维导图(无论学习什么,有学习路线都会事半功倍)
- Flutter进阶学习全套手册
- Flutter进阶学习全套视频
大概就上面这几个步骤,这样学习不仅高效,而且能系统的学习新的知识。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
以参考我的学习方法)
- Flutter 的思维导图(无论学习什么,有学习路线都会事半功倍)
[外链图片转存中…(img-xiXSSeE4-1715558354791)]
- Flutter进阶学习全套手册
[外链图片转存中…(img-7nFSEFgj-1715558354792)]
- Flutter进阶学习全套视频
[外链图片转存中…(img-4tnBPQhT-1715558354793)]
大概就上面这几个步骤,这样学习不仅高效,而且能系统的学习新的知识。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!