什么是MVP模式?
     这个MVP可不是腾讯游戏《王者荣耀》中的MVP。我们今天要讨论的MVP其实同MVC一样,是一种编程模式和思想,也许更准确地讲是一种架构。

MVP和MVC的区别
     提到MVP模式,大家自然避免不了要和我们以前常用的MVC模式进行对比。关于MVP和MVC的区别,此处我们就不重复造轮子了,给大家推荐两篇文章:

两张图看懂Android开发中MVC与MVP的区别
Android中MVP模式讲解及实践

MVP模式的介绍
先上两张示例图(网上的图大同小异,都一样)

mvp耦合图示:

mvp使用交互流程图示:

MVP 全称是Model - View - Presenter ,是模型(model)-视图(view)-呈现器(presenter)的缩写。

Model:业务逻辑和数据处理(数据库存储操作,网络数据请求,复杂算法,耗时操作)。

View : 对应于Activity,负责View的绘制以及与用户交互。

Presenter:负责完成View于Model间的交互 (有一点还需要注意,presenter是双向绑定的关系,因此,在设计的时候就要注意接口和抽象的使用,尽可能的降低代码的耦合度,这也是mvp的宗旨)。

MVP模式使用示例佐证
下面参照网上有个比较通俗的示例,来讲述下MVP 模式的使用。
以最常用的网络数据请求为例。
先来明确下MVP中各个环节的责任划分,然后照此进行代码布局。

责任划分:
Model: 定义并实现获取数据操作(如数据库读取、网络加载)的接口
View: 定义并在Activity,Fragment等中实现用于界面处理(初始化,数据展示)的接口
Presenter: 定义用于调用Model中的数据请求方法的接口,实现此接口,并实现Model中定义的数据请求的接口

项目结构:

Step 1/编写Model逻辑:

数据请求接口(如数据库读取、网络加载)的定义:

/**
* Model层接口---实现该接口的类负责实际的获取数据操作,如数据库读取、网络加载
*/
public interface IModel {

void getData(Model.LoadDataCallback callback);
}
1
2
3
4
5
6
7
数据请求接口的实现:

/**
* 实现IModel接口,负责实际的数据获取操作(数据库读取,网络加载等),然后通过自己的接口(LoadDataCallback)反馈出去
*/
public class Model implements IModel {

@Override
public void getData(final LoadDataCallback callback) {
//数据获取操作,如数据库查询、网络加载等
new Thread() {
@Override
public void run() {
try {
//模拟耗时操作
Thread.sleep(3000);
//获取到了数据
String data = "我是获取到的数据";
//将获取的数据通过接口反馈出去
callback.success(data);
} catch (InterruptedException e) {
e.printStackTrace();
//获取数据失败的回调
callback.failure();
}
}
}.start();
}

/**
*
* 用于回传请求的数据的回传
*/
public interface LoadDataCallback {

void success(String taskId);

void failure();
}
}

 
Step 2/编写View逻辑:
定义用于界面处理(初始化,数据展示)的接口

/**
* View层接口---执行各种UI操作,定义的方法主要是给Presenter中来调用的
*/
public interface IView {

void showLoadingProgress(String message);

void showData(String text);
}

在Activity,Fragment等中对接口的实现:

/**
* 实现IView接口并实现各种UI操作的方法(其他的业务逻辑在Presenter中进行操作)
*/
public class ViewActivity extends AppCompatActivity implements IView {

private Button mBtnShowToast;
private TextView mText;
private MyHandler mHandler = new MyHandler(ViewActivity.this);
private IPresenter mPresenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mvp);

//实例化Presenter,并将实现了IView接口的类传入进去
mPresenter = new Presenter(ViewActivity.this);

mBtnShowToast = findViewById(R.id.btn_show_toast);
mText = findViewById(R.id.text);

mBtnShowToast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//通过Presenter来实现业务逻辑操作,View层只负责UI相关操作
mPresenter.loadData();
}
});
}

@Override
public void showLoadingProgress(final String message) {
mHandler.post(new Runnable() {
@Override
public void run() {
mText.setText(message);
}
});
}

@Override
public void showData(final String text) {
mHandler.post(new Runnable() {
@Override
public void run() {
mText.setText(text);
}
});
}

private static class MyHandler extends Handler {

//弱引用,防止内存泄露
WeakReference<ViewActivity> weakReference;

public MyHandler(ViewActivity activity) {
this.weakReference = new WeakReference<ViewActivity>(activity);
}

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
weakReference.get().mText.setText(msg.what);
break;
}
}
}
}
 
Step 3/编写presenter逻辑(重点关注)
presenter层很重要,为什么这样说呢?
因为MVP模式中,View和Model是不直接交互的,而是通过presenter这个纽带来进行交互-----------View通过presenter对象来调用Model中数据请求的接口,而Model中数据请求的结果会通过presenter中定义的接口回调给presenter,然后presenter在通知给View。

定义用于调用Model中的数据请求方法的接口:
具体实现:

/**
* Presenter层接口---控制Model层的数据操作及调用View层的UI操作来完成“中间人”工作
*/
public interface IPresenter {

void loadData();

}

定义用于调用Model中的数据请求方法的接口,实现此接口,并实现M中定义的数据请求的接口

/**
* Presenter层接口---控制Model层的数据操作及调用View层的UI操作来完成“中间人”工作.
* 用于model和view的相关方法的调用
*/
public class Presenter implements IPresenter, Model.LoadDataCallback {

private final IView mView;
private final Model mModel;

public Presenter(IView view) {
mView = view;
mModel = new Model();
}

@Override
public void loadData() {
mView.showLoadingProgress("加载数据中");
mModel.getData(Presenter.this);
}

@Override
public void success(String data) {
mView.showData(data);
}

@Override
public void failure() {

}
}

大家要多看,多试验,最重要的是理解思路,理解思路,理解思路。重要的事情说三遍。Google官方的MVP代码大家可以去研读一下,是同一个模式,只不过它把好多接口集成在一个接口文件中,防止代码碎片化,大家研读时记住这一点,就不会困惑了。
————————————————
版权声明:本文为CSDN博主「游走的大千世界的烤腰子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhangqunshuai/article/details/82562801

MVP模式(转)的更多相关文章

  1. [译]Google官方关于Android架构中MVP模式的示例

    概述 该示例(TODO-MVP)是后续各种示例演变的基础,它主要演示了在不带架构性框架的情况下实现M-V-P模式.其采用手动依赖注入的方式来提供本地数据源和远程数据源仓库.异步任务通过回调处理. 注意 ...

  2. Android MVP模式 谷歌官方代码解读

    Google官方MVP Sample代码解读 关于Android程序的构架, 当前(2016.10)最流行的模式即为MVP模式, Google官方提供了Sample代码来展示这种模式的用法. Repo ...

  3. 在Andoid开发中使用MVP模式来解耦,增加可测试性

    by Jeff Angelini posted on 7/20/2011 2:35:00 PM 将应用程序UI的表现从Ui的逻辑中分离是一个好的想法.这种分离减少了代码耦合,代码更加干净, 甚至可以有 ...

  4. MVP模式(Android)

    以前在写项目的时候,没有过多考虑架构模式的问题,因为之前一直做J2EE开发,而J2EE都是采用MVC模式进行开发的,所以在搭建公司项目的时候,也是使用类似MVC的架构(严格来讲,之前的项目还算不上MV ...

  5. Android -- 思考 -- 为什么要在项目中使用MVP模式

    1,其实有时候一直在找借口不去思考这个问题,总是以赶项目为由,没有很认真的思考这个问题,为什么我们要在项目中使用MVP模式,自己也用MVP也已经做了两个项目,而且在网上也看了不少的文章,但是感觉在高层 ...

  6. iOS学习之MVC,MVVM,MVP模式优缺点

    为什么要关注架构设计? 因为假如你不关心架构,那么总有一天,需要在同一个庞大的类中调试若干复杂的事情,你会发现在这样的条件下,根本不可能在这个类中快速的找到以及有效的修改任何bug.当然,把这样的一个 ...

  7. MVP模式和MVVM模式

    MVP模式 模型-视图-表示器,也就是MVP模式.是mvc模式的一种衍生模式,专注于改进表示逻辑. 与MVC不同,来自view的调用将委托给presenter(表示器),表示器通过接口与view对话. ...

  8. 控件使用经验-MVP模式+控件封装

    项目背景 几年前参与了一个面向学校的人事管理软件的开发,基于WinForm平台.今天主要想谈一谈其中关于控件的使用经验.这个项目我们大量使用了第三方控件.由于这个产品的生命周期很长,我们在设计时要考虑 ...

  9. MVP模式在Android项目中的使用

    以前在写项目的时候,没有过多考虑架构模式的问题,因为之前一直做J2EE开发,而J2EE都是采用MVC模式进行开发的,所以在搭建公司项目的时候,也是使用类似MVC的架构(严格来讲,之前的项目还算不上MV ...

  10. MVP模式

    一.软件设计鼻祖MVC 1.1.MVC 第一次听到MVC这个名词是在C#中,相信对于MVC大家都已经很熟悉了,作为一种软件设计模式,MVC这个概念已经诞生好多年了. 如果你已经开发一段时间的iOS应用 ...

随机推荐

  1. ThreadLocal最终版本

    ThreadLocal工作原理 目录 ThreadLocal工作原理 一.官方文档描述 二.为什么使用ThreadLocal 2.1.案例 三.ThreadLocal和syncronized关键字区别 ...

  2. KCL 语言和 YAML 字符串的区别是什么?一文完全解答

    什么是 YAML YAML 是一种数据序列化语言,通常用于编写配置文件.YAML 代表另一种标记语言或YAML 不是标记语言(递归首字母缩写词),YAML 通常用于数据,而不是文档.YAML 还是一种 ...

  3. es 6中for in与for of适用对象

    在 ES6 中提供了 for-of,可以很方便的遍历数组和类数组,但是却不能遍历对象,这是为什么,与 for-in 仅仅相差一个单词,用途也是遍历,为什么却不能使用在对象上? 查资料后得知,原来 ES ...

  4. JetBrains之全家桶破解

    JetBrains之全家桶破解(idea,rider....) 链接之....JETBRA.IN 打开上面的链接 随便点击下图中一个可用的链接,进入之后看下一步. 打开上一步的链接之后,下载下图中红框 ...

  5. 开源 IM 系统 tinode 部署教程| WSL 环境

    背景 我们的需求是在本地部署一套 IM 系统,选择 tinode.为便于后端启动,我们采用 WSL 环境,配合 docker 安装数据库,来启动 IM 应用. 解决 WSL 启动前端和后台服务 cmd ...

  6. 复习第7点-7.SpringMVC 的响应方式

    1.使用ServletAPI实现转发 /* 使用HttpServletRequest对象实现请求转发 */ @RequestMapping("/httpServletRequest" ...

  7. Spring全家桶(二)之SpringMVC总结

    SpringMVC面试题 关于Spring,SpringMVC,SpringBoot三者的源码等解析,会在博客园上详细整理! 这个仅仅是面试题整理 SpringMVC工作原理 1.是否需要在类路径中使 ...

  8. npm 局部安装 jbrowse

    #此处不要加 -g参数 , -g 是全局安装 npm install @jbrowse/cli #用npx 才能使用这个包,无法按照官方文档直接使用 npx jbrowse --version

  9. Linux系统Shell脚本第二章:条件测试、正整数字符串比较与if、case语句

    目录 一.条件测试 1.三种测试方法 2. 正整数值比较 3.字符串比较 4.逻辑测试 二.脚本中常用命令 1.echo命令 2.date命令 3.cal命令 4.tr命令 5.cut命令 6.sor ...

  10. EL表达式读取属性不存在的异常,读取类的属性不存在,无法调用到该属性

    修改类中的名称,必须要符合2JavaBaen要求,否则EL表达式读取不到.