android MVP模式介绍与实战

描述


MVP模式是什么?MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。

MVC和MVP的区别?


为什么会出现MVP模式呢?这是因为原有的MVC模式有一些短板。比如在android开发中,activity充当着MVC中Controller的角色,但是在实际开发中处理view的逻辑和角色。当业务界面复杂时我的activity会显得很庞大。于是出现了MVP模式,它新增了一个Presenter角色用于处理数据和界面的模型以及逻辑,Activity仅仅用于展示界面和用户交互,这样就解决了MVC中角色不清的局面。

所以,MVP与MVC的重大区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。

在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。 在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示,即View。所以,在MVC模型里,Model不依赖于View,但是View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。

MVC模式结构

  • Model 业务逻辑和实体模型
  • Controller 对应Activity
  • View 视图以及布局文件

MVP模式结构

  • Model: 业务逻辑和实体模型
  • View:用户交互和视图显示,在android中对应activity
  • Presenter: 负责完成View于Model间的逻辑和交互

小节:MVP模式相当于在MVC模式中又加了一个Presenter用于处理模型和逻辑,将View和Model完全独立开,在android开发中的体现就是activity仅用于显示界面和交互,activity不参与模型结构和逻辑,

实战

谷歌官网给了我们一个MVP模式实战的例子,它是一个类似记事本的app,源码地址在:https://github.com/googlesamples/android-architecture

官方案例的框架图如下:

看完源码后发现其不适合初学者理解,于是我自己写了一个demo方便大家理解。

demo源码地址:https://github.com/halibobo/AndroidMvpExample

源码主要类的结构如下

下面来看源码

View层对应的是MainActivity,它继承了抽离出View所有操作方法的接口OperationView

/**
* *Created by su on 2016/6/22.
*/
public interface OperationView { void showCreatingPhone(); void showPhoneCountChange(); void showNoPhone(); void showFactoryBusy(); void showCreatedPhone();
}

MainActivity具体对每个操作进行了具体的实现

    public class MainActivity extends AppCompatActivity implements OperationView {

    private ListView listView;

    private Button btnCreate;

    private PhonePresenter phonePresenter;

    private ProgressDialog mLoadingDialog;
ArrayAdapter<Phone> arrayAdapter;
private Toast toast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar); PhoneFactory phoneFactory = new PhoneFactory();
phoneFactory.createPhone("nokia",555);
phonePresenter = new PhonePresenter(phoneFactory, this);
btnCreate = (Button) findViewById(R.id.btnCreate);
listView = (ListView) findViewById(R.id.listView);
arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, phoneFactory.getPhonesList());
btnCreate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
phonePresenter.addPhone(new Phone("iphone", 4000+ new Random().nextInt(1000)));
}
}); listView.setAdapter(arrayAdapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
phonePresenter.removePhone(position);
}
}); } @Override
public void showCreatingPhone() {
mLoadingDialog = new ProgressDialog(this);
mLoadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mLoadingDialog.setMessage("工厂正在生产手机");
mLoadingDialog.setCancelable(true);
mLoadingDialog.show();
} @Override
public void showPhoneCountChange() {
arrayAdapter.notifyDataSetChanged();
} @Override
public void showNoPhone() {
findViewById(R.id.noPhone).setVisibility(View.VISIBLE);
} @Override
public void showFactoryBusy() {
showToast("工厂繁忙,请稍后再试!");
} @Override
public void showCreatedPhone() {
if (mLoadingDialog != null && mLoadingDialog.isShowing()) {
mLoadingDialog.dismiss();
}
mLoadingDialog = null;
showToast("新生产出一台手机!");
findViewById(R.id.noPhone).setVisibility(View.GONE);
} private void showToast(String string) {
if (toast == null) {
toast = Toast.makeText(this, string, Toast.LENGTH_SHORT);
}else{
toast.setText(string);
}
toast.show();
}
}

Model层对应的是PhoneFactory,它处理和数据相关的一些简单操作

	 /**
* Created by su on 2016/6/22.
*/ /**
* 手机工厂类
*/ public class PhoneFactory {
private ArrayList<Phone> phonesList = new ArrayList<>(); public void addPhone(Phone phone) {
phonesList.add(phone);
} public void removePhone(Phone phone) {
phonesList.remove(phone);
} public void removePhone(int index) {
if (index >= 0 && index < phonesList.size()) {
phonesList.remove(index);
}
} public void createPhone(String name, double price) {
Phone phone = new Phone(name, price);
phonesList.add(phone);
} public ArrayList<Phone> getPhonesList() {
return phonesList;
} public int getPhoneCounts() {
return phonesList.size();
}
}

下面是最为重要的Presenter层 对应代码中的PhonePresenter,它处理界面逻辑和数据模型等,源码如下:

public class PhonePresenter implements TaskPresenter{

    private final PhoneFactory phoneFactory;
private final OperationView operationView; private static final long createPhoneTime = 2000;
private static final int msgWhat = 0x102; public PhonePresenter(@NonNull PhoneFactory phoneFactory, @NonNull OperationView operationView) {
this.phoneFactory = phoneFactory;
this.operationView = operationView;
} @Override
public void addPhone(Phone phone) {
operationView.showPhoneCountChange();
if (mHandler.hasMessages(msgWhat)) {
operationView.showFactoryBusy();
return;
}
Message message = new Message();
message.what = msgWhat;
message.obj = phone;
mHandler.sendMessageDelayed(message, createPhoneTime);
operationView.showCreatingPhone();
} @Override
public void removePhone(int index) {
phoneFactory.removePhone(index);
if (phoneFactory.getPhoneCounts() <= 0) {
operationView.showNoPhone();
}
operationView.showPhoneCountChange();
} @Override
public void removePhone(Phone phone) { } public ArrayList<Phone> getPhones() {
ArrayList<Phone> phones = phoneFactory.getPhonesList();
if (phones.isEmpty()) {
operationView.showNoPhone();
}
return phones;
} private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
phoneFactory.addPhone((Phone)msg.obj);
operationView.showCreatedPhone();
operationView.showPhoneCountChange();
}
};
}

运行效果图如下:

总结

使用MVP模式会使得代码多出一些接口但是使得代码逻辑更加清晰,尤其是在处理复杂界面和逻辑时,我们可以对同一个activity将每一个业务都抽离成一个Presenter,这样代码既清晰逻辑明确又方便我们扩展。当然如果我们的业务逻辑本身就比较简单的话使用MVP模式就显得,没那么必要。所以我们不需要为了用它而用它,具体的还是要要业务需要

谢谢大家

demo地址在:https://github.com/halibobo/AndroidMvpExample

android MVP模式介绍与实战的更多相关文章

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

    主要学习这位大神的博客:简而易懂 Android MVP模式 简单易懂的介绍方式 https://segmentfault.com/a/1190000003927200

  2. Android MVP模式简单易懂的介绍方式 (三)

    Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 讲完M和P,接下来就要讲V了.View ...

  3. Android MVP模式简单易懂的介绍方式 (二)

    Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 上一篇文章我们介绍完了Model的创建 ...

  4. Android MVP模式简单易懂的介绍方式 (一)

    Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 最近正在研究Android的MVP模式 ...

  5. Android MVP模式

    转自http://segmentfault.com/blogs,转载请注明出处Android MVP Pattern Android MVP模式\[1\]也不是什么新鲜的东西了,我在自己的项目里也普遍 ...

  6. android MVP模式简单介绍

    原文 http://zhengxiaopeng.com/2015/02/06/Android%E4%B8%AD%E7%9A%84MVP/ 前言 MVP作为一种MVC的演化版本在Android开发中受到 ...

  7. Android MVP模式简单介绍:以一个登陆流程为例

    老的项目用的MVC的模式,最近完成了全部重构成MVP模式的工作,虽然比较麻烦,好处是代码逻辑更加清楚.简洁,流程更加清晰,对于后续版本迭代维护都挺方便.对于一些想要学习MVP模式的同学来讲,百度搜出来 ...

  8. Android mvp模式、mvvm模式

    MVC和MVP的区别2007年08月08日 星期三 上午 09:23 MVC和MVP到底有什么区别呢? 从这幅图可以看到,我们可以看到在MVC里,View是可以直接访问Model的!从而,View里会 ...

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

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

随机推荐

  1. [LeetCode] Sparse Matrix Multiplication

    Problem Description: Given two sparse matrices A and B, return the result of AB. You may assume that ...

  2. [PaPaPa][需求说明书][V0.3]

    PaPaPa软件需求说明书V0.3 前   言 不好意思,本文是没有前言的. 别说是前言了,其实关于界面的内容我也是不打算写!!   因为我知道你们想要的界面是这样的: 再不济也应该是这样的: 但是我 ...

  3. 【Xamarin报错】visual studio android 模拟器部署卡住

    模拟器启动成功,但是部署一直等待中,没有反应. 1>Starting deploy 5" KitKat (4.4) XXHDPI Phone ...1>Starting emul ...

  4. PSAM卡与CPU(用户卡)的操作过程

    最近我一直在研究关于通过国密PSAM卡作为安全模块来读写cpu(用户卡)的问题 其实,两者都是卡片,或者说都是从设备.它们之间是无法相互访问的. 实际上,PSAM 卡是作为秘密密钥的载体,专门执行加密 ...

  5. log4net各种Filter使用

    log4net里面的filter类常用的为: 1.DenyAllFilter 拒绝所用的日志输出 <filter type="log4net.Filter.LevelMatchFilt ...

  6. Android debug时一直处于waiting for debugger解决办法

    问题:android 调试卡在:Waiting for Debugger - Application XXX is waiting for the debugger to Attach" 解 ...

  7. 编辑器之神VIM 总结(一) 基础部分

     版本号 说明 作者 日期  1.0  vim基础知识 Sky Wang 2013/06/19       概要 vim和emacs,一个是编辑器之神,一个是神一样的编辑器.他们被称是UNIX系统下的 ...

  8. Mysql 修改密码及重置密码方法

    修改密码: //选择数据库 use mysql; //修改密码 update user set password=password('新密码') where user='root'; //立即生效 f ...

  9. fis3使用环境

    1.全局安装nodejs 2.安装http-server npm install http-server -g 3.安装fis3 npm install -g fis3 如要限制版本号写法是:npm ...

  10. 内存中OLTP(Hekaton)里的事务日志记录

    在今天的文章里,我想详细讨论下内存中OLTP里的事务日志如何写入事务日志.我们都知道,对于你的内存优化表(Memory Optimized Tables),内存中OLTP提供你2个持久性(durabi ...