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文件 ...
随机推荐
- JavaScript console 用法大全
对于前端开发者来说,在开发过程中需要监控某些表达式或变量的值的时候,用 debugger 会显得过于笨重,取而代之则是会将值输出到控制台上方便调试.最常用的语句就是console.log(expres ...
- 一、记一次失败的 CAS 搭建 之 环境配置
==================================================================================================== ...
- 程序使用嵌套的for循环找出2〜100中的素数
#import <Foundation/Foundation.h> int main () { /* local variable definition */ int i, j; ; i& ...
- Oracle和Redhat下载地址
Oracle RedHat 用户名:zhangwei900808@126.com 密码:@XxxxxXxxxxxx 有网友想要的,请在留言板给我留言,我会把用户名和密码发给你!
- 1062: [NOI2008]糖果雨 - BZOJ
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1062 神题一个,直接讲思路了(全都是看别人的) 首先我们把一个云用一个平面上的点( ...
- @Entity设置OneToMany
Hibernate设置bean映射数据库的方式有配置模式与注解模式,下面通过注解模式配置OneToMany @Entity @Table(name="csdnbbs_sys_catalog& ...
- [转载]C#缓存absoluteExpiration、slidingExpiration两个参数的疑惑
看了很多资料终于搞明白cache中absoluteExpiration,slidingExpiration这两个参数的含义. absoluteExpiration:用于设置绝对过期时间,它表示只要时间 ...
- 【C++基础】关键字static 局部变量
1.局部变量 static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值: int test(int j){ static int i=10; i=i+j ...
- ***CI异常记录到日志:CodeIgniter中设计一个全局exception hook
在CodeIgniter中,当发生异常时,经常要通知系统管理员,因此有必要在全局的高度上 捕捉异常,因此可以写一个hook, 比如在config目录的hook.php中,加入: $hook['pre_ ...
- DJANGO输出HIGHCHARTS数据的样例
XXX,DJANGO ORM里确实有很深的水,需要慢慢理解.. 比如: 获取指定时间段的数据: app.deployversion_set.filter(add_date__range=(date_s ...