Android 中的MVP 模式
MVP模式的核心思想:
MVP把Activity中的UI逻辑抽象成View接口,把业务逻辑抽象成功接口,Model类还是原来的Model。
MVC

- 其中View层其实就是程序的UI界面,用于向用户展示数据以及接收用户的输入
- 而Model层就是JavaBean实体类,用于保存实例数据
- Controller控制器用于更新UI界面和数据实例
View层接受用户的输入,然后通过Controller修改对应的Model实例;同时,当Model实例的数据发生变化的时候,需要修改UI界面,可以通过Controller更新界面。View层也可以直接更新Model实例的数据,而不用每次都通过Controller,这样对于一些简单的数据更新工作会变得方便许多。
MVP
MVP与MVC最不同的一点是M与V是不直接关联的也是就Model与View不存在直接关系,这两者之间间隔着的是Presenter层
Model
Model 是用户界面需要显示数据的抽象,也可以理解为从业务数据(结果)那里到用户界面的抽象(Business rule, data access, model classes)
View
视图这一层体现的很轻薄,负责显示数据、提供友好界面跟用户交互就行。MVP下Activity和Fragment体现在了这一层,Activity一般也就做加载UI视图、设置监听再交由Presenter处理的一些工作,所以也就需要持有相应Presenter的引用。例如,Activity上滚动列表时隐藏或者显示Acionbar(Toolbar),这样的UI逻辑时也应该在这一层。另外在View上输入的数据做一些判断时,例如,EditText的输入数据,假如是简单的非空判断则可以作为View层的逻辑,而当需要对EditText的数据进行更复杂的比较时,如从数据库获取本地数据进行判断时明显需要经过Model层才能返回了,所以这些细节需要自己掂量。
Presenter
Presenter这一层处理着程序各种逻辑的分发,收到View层UI上的反馈命令、定时命令、系统命令等指令后分发处理逻辑交由业务层做具体的业务操作,然后将得到的 Model 给 View 显示。

这就是MVP模式,现在这样的话,Activity的工作的简单了,只用来响应生命周期,其他工作都丢到Presenter中去完成。从上图可以看出,Presenter是Model和View之间的桥梁,为了让结构变得更加简单,View并不能直接对Model进行操作,这也是MVP与MVC最大的不同之处。
优点
- 分离了视图逻辑和业务逻辑,降低了耦合
- Activity只处理生命周期的任务,代码变得更加简洁
- 视图逻辑和业务逻辑分别抽象到了View和Presenter的接口中去,提高代码的可阅读性
- Presenter被抽象成接口,可以有多种具体的实现,所以方便进行单元测试
- 把业务逻辑抽到Presenter中去,避免后台线程引用着Activity导致Activity的资源无法被系统回收从而引起内存泄露和OOM
代码变得更加简洁
使用MVP之后,Activity就能瘦身许多了,基本上只有FindView、SetListener以及Init的代码。其他的就是对Presenter的调用,还有对View接口的实现。这种情形下阅读代码就容易多了,而且你只要看Presenter的接口,就能明白这个模块都有哪些业务,很快就能定位到具体代码。Activity变得容易看懂,容易维护,以后要调整业务、删减功能也就变得简单许多。
方便进行单元测试
MVP中,由于业务逻辑都在Presenter里,我们完全可以写一个PresenterTest的实现类继承Presenter的接口,现在只要在Activity里把Presenter的创建换成PresenterTest,就能进行单元测试了,测试完再换回来即可。万一发现还得进行测试,那就再换成PresenterTest吧。
避免内存泄露
Android APP 发生OOM的最大原因就是出现内存泄露造成APP的内存不够用,而造成内存泄露的两大原因之一就是Activity泄露(Activity Leak)(另一个原因是Bitmap泄露(Bitmap Leak))
Java一个强大的功能就是其虚拟机的内存回收机制,这个功能使得Java用户在设计代码的时候,不用像C++用户那样考虑对象的回收问题。然而,Java用户总是喜欢随便写一大堆对象,然后幻想着虚拟机能帮他们处理好内存的回收工作。可是虚拟机在回收内存的时候,只会回收那些没有被引用的对象,被引用着的对象因为还可能会被调用,所以不能回收。
Activity是有生命周期的,用户随时可能切换Activity,当APP的内存不够用的时候,系统会回收处于后台的Activity的资源以避免OOM。
采用传统的MV模式,一大堆异步任务和对UI的操作都放在Activity里面,比如你可能从网络下载一张图片,在下载成功的回调里把图片加载到 Activity 的 ImageView 里面,所以异步任务保留着对Activity的引用。这样一来,即使Activity已经被切换到后台(onDestroy已经执行),这些异步任务仍然保留着对Activity实例的引用,所以系统就无法回收这个Activity实例了,结果就是Activity Leak。Android的组件中,Activity对象往往是在堆(Java Heap)里占最多内存的,所以系统会优先回收Activity对象,如果有Activity Leak,APP很容易因为内存不够而OOM。
采用MVP模式,只要在当前的Activity的onDestroy里,分离异步任务对Activity的引用,就能避免 Activity Leak。
MVP 使用
MVP的主要特点就是把Activity里的许多逻辑都抽离到View和Presenter接口中去,并由具体的实现类来完成。

- 创建IPresenter接口,把所有业务逻辑的接口都放在这里,并创建它的实现PresenterCompl(在这里可以方便地查看业务功能,由于接口可以有多种实现所以也方便写单元测试),IPresenter持有 IView,调用 IView 中的方法
- 创建IView接口,把所有视图逻辑的接口都放在这里,其实现类是当前的Activity/Fragment
- 由UML图可以看出,Activity里包含了一个IPresenter,而PresenterCompl里又包含了一个IView并且依赖了Model。Activity里只保留对IPresenter的调用,其它工作全部留到PresenterCompl中实现
- Model并不是必须有的,但是一定会有View和Presenter
DMEO
简单的登陆界面的例子
- 登陆 view 接口
1 |
package io.github.xuyushi.androidmvpdemo.Login.view; /** |
登陆Presenter接口
1 |
package io.github.xuyushi.androidmvpdemo.Login.presenter; /** |
实现Presenter接口
1 |
package io.github.xuyushi.androidmvpdemo.Login.presenter; import android.os.Handler; import io.github.xuyushi.androidmvpdemo.Login.model.User; |
定义model
1 |
package io.github.xuyushi.androidmvpdemo.Login.model; /** |
在 Activity 中实现 view接口
1 |
package io.github.xuyushi.androidmvpdemo.Login.view; import android.os.Bundle; |
源码地址
https://github.com/xuyushi/AndroidMVPDemo
Android 中的MVP 模式的更多相关文章
- android中的MVP模式
1.建立bean public class UserBean { private String mFirstName; private String mLastName; public UserBea ...
- Android -- 思考 -- 为什么要在项目中使用MVP模式
1,其实有时候一直在找借口不去思考这个问题,总是以赶项目为由,没有很认真的思考这个问题,为什么我们要在项目中使用MVP模式,自己也用MVP也已经做了两个项目,而且在网上也看了不少的文章,但是感觉在高层 ...
- Android上实现MVP模式的途径
今天我想分享我在Android上实现MVP(Model-View-Presenter)模式的方法.如果你对MVP模式还不熟悉,或者不了解为什么要在Android应用中使用MVP模式,推荐你先阅读这篇维 ...
- Java(Android)编程思想笔记03:在Android开发中使用MVP模式
1. MVP模式简介: MVC模式相信大家肯定是比较熟悉的:M-Model-模型.V-View-视图.C-Controller-控制器. MVP作为MVC的演化版本,那么类似的MVP所对应的意义:M- ...
- 在Andoid开发中使用MVP模式来解耦,增加可测试性
by Jeff Angelini posted on 7/20/2011 2:35:00 PM 将应用程序UI的表现从Ui的逻辑中分离是一个好的想法.这种分离减少了代码耦合,代码更加干净, 甚至可以有 ...
- Android中的MVP架构初探
说来羞愧,MVP的架构模式已经在Android领域出现一两年了.可是到今天自己才開始Android领域中的MVP架构征程. 闲话不多说,開始吧. 一.架构演变概述 我记得我找第一份工作时,面试官问我& ...
- Android中的启动模式(下)
在这篇文章中,我会继续跟大家分享有关于Android中启动模式的相关知识.当然,如果对这个启动模式还不完全了解或者没有听过的话,可以先看看我之前写的有关于这个知识点的入门篇Android的启动模式(上 ...
- Android中Activity启动模式详解
在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. An ...
- Android中Activity启动模式探索
Android中启动模式(launchMode)分为standard, singleTop, singleTask, singleInstance四种,可通过AndroidManifest.xml文件 ...
随机推荐
- TabControl控件
private void Form1_Load(object sender, EventArgs e) { #region 显示样式 tabControl1.ImageList = imageList ...
- 【jquery插件】收藏
http://www.oschina.net/project/tag/356/jquery-file-upload
- 慎用ReentrantLock
前言: 代码简洁与性能高效无法两全其美,本文章专注于并发程序的性能,如果您追求代码简洁,本文章可能不太适合,本文章属于Java Concurrency in Practice读书笔记. 在java5中 ...
- jquery bind()方法与live()方法的区别
jquery bind() 方法和 live() 方法都可以绑定元素事件. <!DOCTYPE html> <html> <head> <meta chars ...
- 如何安装Favicon
如何安装Favicon favicon.ico图像放在根目录下(也可以是其他目录)在页面源文件的<head></head>标签之间插入 <link rel="s ...
- Quartz任务调度快速入门(转)
概述 了解Quartz体系结构 Quartz对任务调度的领域问题进行了高度的抽象,提出了调度器.任务和触发器这3个核心的概念,并在org.quartz通过接口和类对重要的这些核心概念进行描述: ●Jo ...
- Chp2: Linked List
2.2 Implement an algorithm to find the kth to last element of a singly linked list. Just using " ...
- POJ 3191 The Moronic Cowmpouter(进制转换)
题目链接 题意 : 将一个10进制整数转化为-2进制的数. 思路 :如果你将-2进制下的123转化为十进制是1*(-2)^2+2*(-2)^1+3*(-2)^0.所以十进制转化为-2进制就是一个逆过程 ...
- android dialog 原来dialog对话框也有自己的按键监听事件 onKeyDown方法
探讨在一个activity中按menu键时弹出自己定义的dialog(自定义菜单对话框)时,再按一次手机的menu键发现这个自定义的dialog菜单并没有关闭,原来是这个dialog内部也有onKey ...
- 玩转redis
http://www.cnblogs.com/huangxincheng/p/5002794.html