什么是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. 将python2.7项目转为Python3问题记录

    将一个Python2.7开发的测试工具项目转化为Python3. 工具:Python自带的2to3.py 将所有.py文件进行转化,生成的python3文件为原文件名,python2文件在后面加.ba ...

  2. PULPINO仿真建立

    PULPINO仿真建立 PULPINO主要特点: systemverilog实现 有常规外设,GPIO.SPI.I2C.UART等 有调试接口 总线有AXI,外设总线为APB,扩展性好 脚本为cmak ...

  3. Word19 撰写企业质量管理论文office真题

    1.看到题目要求:打开考试文件下的素材文档"WPS.docx"文件,后续操作均基于此文件,否则不得分. 2.这一步的操作非常简单,打开文件目录进行双击打开即可完成操作. 3.看到题 ...

  4. elementUi-2.13.2版本添加暂无数据

    1.实现效果如下: 2. 代码实现 <el-table empty-taxt="暂无数据"></el-table> css样式设置: .el-table__ ...

  5. datax缺少clickhouse reader插件

    背景:想要把click house的数据源同步到clickhouse,发现Datax没有clickhousereader组件. 1.把clickhousewriter/libs下的所有jar包复制到r ...

  6. Redis Stack(生产适配-仅提供 Redis Stack 服务器) (6.2.4-v2版本)

    一.使用docker安装(生产适配-仅提供 Redis Stack 服务端) (6.2.4-v2版本) 简介 安装命令根据实际部署情况调整 版本地址:官方镜像主页 | 发布版Tags 指定版本命令-推 ...

  7. linux开机出现grub界面

    今天开机时候突然出现grub界面,并且卡在这里,记录一下解决办法 ①输入ls 2. 输入ls (hd0,6)/ 可以看到返回的就是linux系统的根目录,说明这个磁盘就是我们的系统的所在盘 如果ls ...

  8. rocketmq-exporter部署(干货)

    简单介绍 rocketmq_exporter是prometheus提供的用于监控rocketmq运行状态的exporter 环境 系统 版本 CentOS 7.6.1810 (Core) CPU/内存 ...

  9. Java 复习篇2---jdk

    jdk 文件: bin 该路径下存放了各种工具命令, 其中重要的有javac 和Java conf: 改路径下存放了相关配置文件 include: 该路径下存放了一些平台特定的头文件 jmods; 该 ...

  10. html原声启动本地服务器,用http-server启动本地服务器

    第一: 准备node.js环境: 打开cmd,输入:npm install http-server -g 第二: 安装 http-server npm install http-server -g 安 ...