by Jeff Angelini posted on 7/20/2011 2:35:00 PM

将应用程序UI的表现从Ui的逻辑中分离是一个好的想法。这种分离减少了代码耦合,代码更加干净, 甚至可以有更多的单元测试覆盖率。Android在Activity类中绑定了UI 和 UI 逻辑 class。这种绑定,使测试变得困难甚至不可能,因为依赖的代码不能被模拟。 然而,简单的 MVP 模式可以帮助在 Android 应用程序解耦 UI 和 UI 逻辑。

MVP模式全称Model-View-Presenter, 它分离 UI的数据(Model),UI (View)的显示,UI的逻辑 (Presenter)之间的关系。对于 Android来说,View就是Activity,它是用来处理收集用户输入,更新界面的显示; Presenter是用来处理Model和View之间通讯的类; Model用来保存和查询数据,以及数据相关的业务逻辑。接口可以用来解耦这三个组件。一个简单的典型的View用来展示是怎么实现MVP的。

First, our CustomerActivity (the View) will have textboxes for the Customer’s ID, first name, and last name:

private EditText mFirstNameEditText, mLastNameEditText, mIdEditText;

The user will load a customer using the mIdEditText and a Load Button. Likewise, the user will save a customer using a Save Button:

private Button mSaveButton, LoadButton;

We must now create a CustomerPresenter with the following methods:

public CustomerPresenter(ICustomerView View)
public void saveCustomer (String firstName, String lastName)
public void loadCustomer (int id)

We then can wire it all up in the CustomerActivity’s onCreate method:

mCustomerPresenter = new CustomerPresenter(this); mSaveButton.setOnClickListener(this);
mLoadButton.setOnClickListener(this);

The CustomerActivity class must now implement the interfaces OnClickListener (for handling the Button’s OnClickListeners) and ICustomerView (for the CustomerPresenter constructor). The OnClickListener defines the method void onClick(View v), and our method will look like the following:

switch (v.getId()) {
case R.id.saveButton:
mCustomerPresenter.saveCustomer(mFirstNameEditText.getText().toString(),
mLastNameEditText.getText().toString());
break;
case R.id.loadButton:
mCustomerPresenter.loadCustomer(Integer.parseInt(mIdEditText.getText().toString()));
break;

The previous two code sections show that when the Save Button is clicked, the saveCustomer method of our presenter will be called with the Customer’s first name and last name information; and when the Load Button is clicked, the loadCustomer method of our presenter will be called.

We haven’t defined ICustomerView, so we’ll do that now. When loading the customer, the CustomerPresenter will need to be able to update the CustomerActivity’s last name, first name, and ID EditTexts, so ICustomerView will look like the following:

void setLastName (String lastName);
void setFirstName (String firstName);
void setId(int id);

The CustomerActivity’s implementation of these methods will set the corresponding EditText to the value of the parameter.

The CustomerPresenter, then, will look like the following:

private ICustomerView mCustomerView;
private ICustomerModel mCustomerModel;
public CustomerPresenter(ICustomerView view) {
mCustomerView = view;
mCustomerMode = new CustomerModel();
}
@Override
public void saveCustomer(String firstName, String lastName) {
mCustomerModel.setFirstName(firstName);
mCustomerModel.setLastName(lastName);
}
@Override
public void loadCustomer(int id) {
(mCustomerModel.load(id)) {
mCustomerView.setId(mCustomerModel.getId());
mCustomerView.setFirstName(mCustomerModel.getFirstName());
mCustomerView.setLastName(mCustomerModel.getLastName());
}
}

The implementation of the CustomerModel isn’t important for our purposes; we just need to know that it is being saved to a repository of some sort. Furthermore, the CustomerModel is currently tightly-coupled to the CustomerPresenter, which can be remedied by injecting it as a dependency.

The CustomerPresenter allows the CustomerActivity class to be as simple as possible. The activity now only gathers user input for the presenter and provides simple UI update methods for the presenter. Since the CustomerView and CustomerModel implement interfaces and can be injected into the CustomerPresenter, it is not dependent on them. Therefore, they can by mocked, which allows the CustomerPresenter logic to be unit tested.

After Note: This MVP pattern is sometimes referred to as Passive View, since the view only passes along data, either to or from its presenter. The MVP pattern can also be implemented such that the View knows of the model. The view responds to state changes in the model for simple UI updates, while the presenter handles more complex UI logic. This more complex pattern is sometimes referred to as Supervising Controller.

In Android, this can be accomplished by the Model using Java’s Observable class and the View implementing the Observer interface; when something changes in the Model, it can call the Observable’s notifyObservers method. It can also be implemented with Android’s Handler class; when something changes in the Model, it can send a message to a handler that the View injects into it.

在Andoid开发中使用MVP模式来解耦,增加可测试性的更多相关文章

  1. Java(Android)编程思想笔记03:在Android开发中使用MVP模式

    1. MVP模式简介: MVC模式相信大家肯定是比较熟悉的:M-Model-模型.V-View-视图.C-Controller-控制器. MVP作为MVC的演化版本,那么类似的MVP所对应的意义:M- ...

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

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

  3. 转:Android开发中的MVP架构(最后链接资源不错)

    Android开发中的MVP架构 最近越来越多的人开始谈论架构.我周围的同事和工程师也是如此.尽管我还不是特别深入理解MVP和DDD,但是我们的新项目还是决定通过MVP来构建. 这篇文章是我通过研究和 ...

  4. Web前端开发中的MCRV模式(转)

    作者: izujian  来源: baiduux 摘要:针对前端开发中基于ajax的复杂页面开发所面临的代码规模大,难以组织和维护,代码复用性.扩展性和适应性差等问题,本文尝试以MVC思想为 基础,结 ...

  5. 稍微谈一下 javascript 开发中的 MVC 模式

    随着前台开发日益受到重视,客户端代码比重日益增加的今天,如何在javascript开发里应用MVC模式,这个问题似乎会一直被提到,所以偶在这里粗略的谈一下自己的看法吧. MVC模式的基本理念,是通过把 ...

  6. 转: Android开发中的MVP架构详解(附加链接比较不错)

    转: http://www.codeceo.com/article/android-mvp-artch.html 最近越来越多的人开始谈论架构.我周围的同事和工程师也是如此.尽管我还不是特别深入理解M ...

  7. 设计模式笔记之二:Android开发中的MVP架构(转)

    写在前面,本博客来源于公众号文章:http://mp.weixin.qq.com/s?__biz=MzA3MDMyMjkzNg==&mid=402435540&idx=1&sn ...

  8. 二十八、带给我们一种新的编码思路——EFW框架CS系统开发中的MVC模式探讨

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

  9. Android 中的MVP 模式

    MVP模式的核心思想: MVP把Activity中的UI逻辑抽象成View接口,把业务逻辑抽象成功接口,Model类还是原来的Model. MVC 其中View层其实就是程序的UI界面,用于向用户展示 ...

随机推荐

  1. Activity系列讲解---返回结果的处理

    设想一下:由当前Activity跳转到其它Activity,从其它Activity再返回到当前Activity时,如何获取其它Activity存放的数据?下面用一个例子讲解, 点击selsect按钮跳 ...

  2. python class metaclass instance

    >>> class CObj(object):... pass...>>> dir()['CObj', '__builtins__', '__doc__', '__ ...

  3. curses.h的安装和使用

    gcc test.c -o test 用以上命令编译包含curses.h头文件的程序时会出现各种引用未定义的错误,并且已经安装了 kernel-devel ncurese-devel ncurese- ...

  4. Swing中弹出对话框的几种方式_JOptionPane.showMessageDialog等详解

    Swing中弹出对话框的几种方式_JOptionPane.showMessageDialog等详解   在swing中,基于业务的考量,会有对话框来限制用户的行为及对用户的动作进行提示. Swing中 ...

  5. tp5 model 的时间戳

    单独在模型里面设置:(推荐) protected $autoWriteTimestamp = true; // int 型 protected $autoWriteTimestamp = 'datet ...

  6. swift错误 Expressions are not allowed at the top level

    ``` ... earlier we said top-level code isn't allowed in most of your app's source files. The excepti ...

  7. 常用Javascript语法

    1.document.write(""); 输出语句 2.JS中的注释为// 3.传统的HTML文档顺序是:document->html->(head,body) 4. ...

  8. Android中surface,surfaceview,sufaceholder以及surface客户端的关系

    这里以照相机camera功能的实现来解释surface,surfaceview,sufaceholder以及surface客户端(本例子中指的是camera)的关系,surface及其client(客 ...

  9. 转 centos虚拟机环境的构建。

    转自:http://www.cnblogs.com/xiaoluo501395377/archive/2013/03/31/CentOs.html 一.前言 作为一个想从事j2ee后台开发的程序猿,l ...

  10. MS Sql Server

    # 安装SQL2000时总是提示:以前的某个程序安装已经在安装计算机上创建挂起的文件操作 原文:https://zhidao.baidu.com/question/424367402.html # S ...