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. 有了malloc/free为什么还要new/delete ?

    malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符.它们都可用于申请动态内存和释放内存. 对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的 ...

  2. WPF中如何用代码触发按钮Click处理

    btnOk.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));

  3. 使用 Portable Class Library(可移植类库)开发 Universal Windows App

    今天在这里跟大家聊聊关于 Windows Universal 应用夸平台的问题,首先Universal Windows App的定义相信大家已经有所了解了(如果你是一个刚刚接触 Universal A ...

  4. Microsoft 2013 新技术学习笔记 一

    有几年没有关注技术了,最近有点时间想把技术重新捡起来,借着重构手上的一个后台管理框架的机会将微软新的几种技术全部应用一下,从目的上来讲并没有希望能对涉及的技术有很深入的了解,所以这个系列的文章(篇幅不 ...

  5. FastReport.Net在Rozor中的应用

    Webconfig中配置 IIS6.0 <system.web> <httpHandlers> 下增加 <httpHandlers> <add path=&q ...

  6. dell 电脑关闭触摸板的。

    桌面计算机(点击右键)----管理----设备管理器-----鼠标------选择触摸板(ps/2 兼容鼠标)---右击------跟新驱动-------浏览计算机查找------从计算机列表中选择- ...

  7. EFW框架源代码版本升级记录说明

    回<[开源]EFW框架系列文章索引>        EFW框架源代码下载V1.3:http://pan.baidu.com/s/1c0dADO0 EFW框架实例源代码下载:http://p ...

  8. 【转载】CSS 盒子模型

    转处:http://www.cnblogs.com/sunyunh/archive/2012/09/01/2666841.html 说在Web世界里(特别是页面布局),Box Model无处不在.下面 ...

  9. Android加载SO库UnsatisfiedLinkError错误的原因及解决方案

    Android 应用开发者应该对 UnsatisfiedLinkError 这种类型的错误比较熟悉了,这个问题一直困扰着广大的开发者,那么有没有想过有可能你什么都没做错,也会出现这个问题呢? 我们在 ...

  10. ADT-bundle(Android Development Tools)环境配置

    Android开发环境有两套比较主流的:ADT-bundle和Android Studio,前者是Eclipse插件的形式进行开发,后者是Android的官方IDE. ADT环境的配置与调试:(1)安 ...