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. 学习 opencv---(8)非线性滤波:中值滤波,双边滤波

    正如我们上一篇文章中讲到的,线性滤波可以实现很多种不同的图像变换.然而非线性滤波,如中值滤波器和双边滤波器,有时可以达到更好的实现效果. 邻域算子的其他一些例子还有对 二值图像进行操作的形态学算子,用 ...

  2. CROSS APPLY应用实例

    --功能说明:统计每个人的平均分数,新字段[AVG_Score]根据PersonID链接到原表[tbiz_AssScore]上 SELECT [ID] ,[ProjectID] ,[PersonID] ...

  3. iOS 企业设备管理 补充中。。。

    公司的设备都有一个统一的管理方法,以前不太明白,今天看了一下资料. 这里解释了什么是设备管理 Profile Manager creates and distributes configuration ...

  4. 【mongo】mongoVUE使用

    1.查询存在字段"test"的项 {"test":{$exists:true}} 2.在表中插入字段 {$set:{"}} 3.正则匹配 {" ...

  5. GridView模版列中设置

    在GridView模版列中设置如下<asp:TemplateField HeaderText="删除">    <ItemTemplate>         ...

  6. SpringBoot前世今生

    序 本文主要讲述spring boot的由来,即其它诞生的背景,初衷,现状,及对未来的展望. 背景 在很早的年代,J2EE还是java企业级应用的王者规范,EJB风行其道.后来有一个叫Rod John ...

  7. mvc file控件无刷新异步上传操作

    前言 上传文件应该是很常见必不可少的一个操作,网上也有很多提供的上传控件.今天遇到一个问题:input控件file无法进行异步无刷新上传.真真的感到别扭.所以就尝试这去处理了一下.主要分三个部分:上传 ...

  8. ORA-27492 无法运行作业,调度程序不可用

    ORA-27492:无法运行作业;调度程序不可用 ORA-06512: at "SYS.DBMS_ISCHED", line 185 ORA-06512: AT SYS.DBMS_ ...

  9. [转]js实现各种进制的转换

    关键点: parseInt(string, radix).toString(target_radix); 参考:http://www.cnblogs.com/guowei1027/archive/20 ...

  10. URL

    URL的格式:protocol :// hostname[:port] / path / [;parameters][?query]#fragment URL出现了有+,空格,/,?,%,#,& ...