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. angular开发单页面应用--页面资源部分

    关于angular是什么,能够干什么就不在这里解释了,自行搜索了,或者等稍晚一点再解释... angular适合开发单页面应用,这句话在介绍angular的网站和博客里都可以提到.因为angular是 ...

  2. ASP.NET MVC RenderPartial和Partial的区别

    背景:ASP.NET MVC 4.0 @{ Html.RenderPartial(...); } public static void RenderPartial(this HtmlHelper ht ...

  3. 常用js函数封装

    see them... // 获取网址的get参数 var GET = function(name) { var reg = new RegExp("(^|&)" + na ...

  4. 在Web Api中集成protobuf

    安装WebApiContrib.Formatting.ProtoBuf Install-Package WebApiContrib.Formatting.ProtoBuf 注册ProtoBufForm ...

  5. Android SDK Manager无法更新的解决[ 转]

    将下列内容行添加到hosts文件中: 74.125.237.1 dl-ssl.google.com 1.Windows C:\WINDOWS\system32\drivers\etc\Hosts 2. ...

  6. Python之str()与repr()的区别

    Python之str()与repr()的区别 str()一般是将数值转成字符串,主要面向用户.  repr()是将一个对象转成字符串显示,注意只是显示用,有些对象转成字符串没有直接的意思.如list, ...

  7. main 返回值

    int main() 在c中表示返回值时int:也可以不明确给出返回值,默认为int:()表示接受任何参数,main(void)表示不接受任何参数.main(),int main(),main(voi ...

  8. PHP修改表格(增删改)

    要求: 1.熟练shi用  post 和  get  传值        2. php嵌套在HTML中        3.熟练:if 语句(其他语句)的使用 --------------------- ...

  9. iOS监听tableView组头切换事件

    - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSIntege ...

  10. U盘安装centos7 无法进入安装界面,进入dracut命令的解决办法。

    最近想要装一个centos7 玩一玩,就从网上下了个镜像,用UltraISO制作了安装U盘,准备在旧电脑上装一个. 结果始终无法进入安装界面,而是进入了dracut命令行. 从网上找了解决方法: