Android MVP浅析

前言

近期一直在看设计模式相关的资料,每逢结尾都会介绍到 MVC 模式,而最近比较火的却是 MVP 和 MVVM ,更有甚者,将 MVP 和 MVVM 结合起来形成了 MVPVM ,大神的造诣总是让俺望其项背,下面就结合自己的学习,浅析 MVP。

从哪里开始学习呢?当然是从 Google 自身开始咯,Google 推出了自己的官方 MVP 架构例子。源码地址

相关翻译

今天就主要来看看官方写的最基础的 MVP 的例子 todo-mvp。本文不打算讲解里面代码的具体实现,只是从宏观角度看一下,Google是如何实现 MVP 模式的,细节需要自己慢慢体会,每个人的体会都会不一样的。(里面还涉及到了测试相关的东西)

剖析

Step One

首先从 Github 上 clone 下来,然后本地运行起来,效果如下

这是一个简版的便签,相关数据存储在本地数据库中。知道这个 App 是干嘛的,对下面分析相关代码就好理解了。

Step Two

看代码,找关系,官方的代码结构如下

看目录

  • addetitask:添加/修改任务功能
  • statistics:分析功能(位于侧边栏上)
  • taskdetail:查看任务详情
  • tasks:首页界面,展示任务列表
  • data:数据操作相关
  • util:工具类相关

通过目录,这个 App 的相关操作也就一目了然了,接下来就针对 task 目录下的代码进行分析,看看是如何体现 MVP 思想的。

Step Three

分析前,先认识一下 MVP ,至少了解一下代表的含义

MVP (Model-View-Presenter) 该模式包含以下几个方面

  • View:负责绘制 UI 元素、与用户进行交互(Activity/Fragment);
  • View interface:需要 View 实现的接口,View 通过 View interface 与 Presenter 进行交互,降低耦合,方便进行单元测试;
  • Model:负责存储、检索、操纵数据(有时也实现一个Model interface 用来降低耦合);
  • Presenter:作为 View 与 Model 交互的中间纽带,处理与用户交互的负责逻辑。

先掌握上面的基础概念就可以,下面进入正题

Step Four

task 目录下包含了以下几个文件

  • ScrollChildSwipeRefreshLayout:自定义控件,扩展了 SwipeRefreshLayout
  • TasksActivity:程序入口
  • TasksContract:关联了 View 和 Presenter,是个接口
  • TasksFilterType:是个枚举类,里面定义了 Tasks 列表的状态;
  • TasksFragment:展示 Tasks 列表等相关操作的 Fragment;
  • TasksPresenter: Presenter,负责关联 View 和 Model

它们的关系用类图来表示,如下图所示

其中数据类的相关 java 类简化表示了,详细的自行查阅 Github 上的内容

从上面可以看到,Google 首先定义了两个接口文件 BaseView 和 BasePresenter,然后又通过 接口 TasksContract 进行关联,所有用到上面两个接口的都是通过 TasksContract 进行管理。

看上面的图,好像有点繁杂,眼花缭乱的感觉,那就先搬一张 MVP 模式基本的类图,如下

那么结合上图,怎么根据上面进行划分呢,其实非常容易,如下

上面标的还不算特别好,其中 BaseView 也属于 View 里面,BasePresenter 属于 Presenter 范畴

如果大家仔细看的话,就会发现,View 和 Model 直接是没有任何关联的哦,而 Presenter 和 Model 和 View 都是有关联的,现在在和上面标准的类图进行对比,是不是就一目了然啦。如果大家对里面的代码细节感兴趣,请自行查阅源码哦。

对了,说一点,里面的 TasksActivity 的作用就是将 Presenter 和 TasksFragment 关联起来(不贴点代码好像也不行了)

TasksFragment tasksFragment =
            (TasksFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
    if (tasksFragment == null) {
        // Create the fragment
        tasksFragment = TasksFragment.newInstance();
        ActivityUtils.addFragmentToActivity(
                getSupportFragmentManager(), tasksFragment, R.id.contentFrame);
    }

    // Create the presenter
    mTasksPresenter = new TasksPresenter(
            Injection.provideTasksRepository(getApplicationContext()), tasksFragment);

    // Load previously saved state, if available.
    if (savedInstanceState != null) {
        TasksFilterType currentFiltering =
                (TasksFilterType) savedInstanceState.getSerializable(CURRENT_FILTERING_KEY);
        mTasksPresenter.setFiltering(currentFiltering);
    }

Step Five

再来审视一下 MVP

  • M:Model,数据相关,主要就是提供数据的存取功能,像一个数据仓库。Presenter 需要通过 Model 层存、取数据。
  • V:View,用户界面,也就是Activity、Fragment、View控件等,它持有 Presenter 的一个成员变量。通常 View 需要实现一个逻辑接口(示例就是这样做的),将 View 上的操作会转交 Presenter 来年实现。最后,Presenter 调用 View 的逻辑接口将结果返回给 View 元素。
  • P:Presenter,交互中间人。沟通 Model 和 View 的桥梁,将 Model 和 View 之间的关联斩断掉,改为 Presenter 进行联络。这也是和 MVC 模式最大的不同。

MVP 的优点

  • 看类图就知道,首先就是分离了 View 和 Model,降低了耦合
  • 易于维护、测试,一目了然,接口的存在,大大降低了测试的复杂度
  • 代码的可阅性就变的容易了
  • 类型的职责明确,各司其职,应用 MVP 时,会感觉到,结构清晰明了,爽

说完优点,肯定有缺点的,谁让没有一个模式都是金光闪闪,毫无缺点的。

  • Presenter 负责沟通 Model 和 View ,当然不可避免的就会“臃肿”起来
  • 有 View 的存在,就会有 Presenter 的存在,而在实际项目中,一个界面往往有很多的 View 构成,那么想想也是很“激动”的

最后

每个模式的出现,都会解决其他模式的缺点,却又不可避免的带来自身的缺点,然后等着下一模式的出现来解决上一模式的缺点,周而复始。也正是这样的循环,让我们不断的向更好的方向进步,例如: MVVM 的出现。

想要深入学习,查看具体实现方式,请自行下载相关代码进行研究。

参考资料

Android开发艺术探索[M]. 电子工业出版社, 2015.487-494

Android官方MVP架构示例项目解析

Google Android MVP Pattern 知识整理

Android MVP模式 简单易懂的介绍方式

如何设计MVP中的Presentation层

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

推荐阅读更多精彩内容