MVP模式 详解 案例
介绍
MVC:
- View:对应于布局文件
- Model:业务逻辑和实体模型
- Controllor:对应于Activity
实际上关于该布局文件中的数据绑定的操作,事件处理的代码都在Activity中,造成了Activity既像View又像Controller程序员对于MVP的普遍的认识是:代码很清晰,不过增加了很多类当将架构改为MVP以后,Presenter的出现,将Actvity视为View层,Presenter负责完成View层与Model层的交互。现在是这样的:
- View 对应于Activity,负责View的绘制以及与用户交互
- Model 依然是业务逻辑和实体模型
- Presenter 负责完成View和Model间的交互
从并不标准的MVC到MVP的一个转变,减少了Activity的职责,简化了Activity中的代码,将复杂的逻辑代码提取到了Presenter中进行处理。与之对应的好处就是,耦合度更低,更方便的进行测试。MVC与MVP的一个区别示意图:其实最明显的区别就是,MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成。还有一点就是Presenter与View之间的交互是通过接口的。
案例
Activity包(view包)
/*** 梳理此Activity所有需要的方法,将这些方法全部封装到一个接口中* @author 白乾涛*/public interface IUserLoginView {public String getUserName();public String getPassword();public void clearUserName();public void clearPassword();public void toMainActivity(User user);public void showFailedError();public void showLoading();public void hideLoading();}/*** 简单来说,对Activity的所有操作(方法)都被剖离在了两个地方,一个是在IUserLoginView中,这里面都是对Activity的一些最基本的操作* 另一个在Presenter中,比较复杂的【业务逻辑】都会放在这里(目的当然是减少Activity的代码逻辑)* 一定要明白,之所以将Activity中的这些方法剖离在IUserLoginView中,是为了在Presenter中能通过操作IUserLoginView来操作Activity(扩展性)** @author 白乾涛*/public class UserLoginActivity extends Activity implements IUserLoginView, OnClickListener {private EditText id_et_username;private EditText id_et_password;private Button id_btn_login;private Button id_btn_clear;private UserLoginPresenter mUserLoginPrestener = new UserLoginPresenter(this);//这里是将IUserLoginView接口的实例(即Activity)传给了Presenterprivate ProgressBar id_progressbar;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_user_login);id_et_username = (EditText) findViewById(R.id.id_et_username);id_et_password = (EditText) findViewById(R.id.id_et_password);id_btn_login = (Button) findViewById(R.id.id_btn_login);id_btn_clear = (Button) findViewById(R.id.id_btn_clear);id_progressbar = (ProgressBar) findViewById(R.id.id_progressbar);id_btn_login.setOnClickListener(this);id_btn_clear.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.id_btn_login://这里面的两个方法在Presenter中,当我们需要修改业务逻辑时,只需修改Prestener类中的相应方法即可!mUserLoginPrestener.login();break;case R.id.id_btn_clear:mUserLoginPrestener.clear();break;}}//******************************************************************************************@Overridepublic String getUserName() {return id_et_username.getText().toString();}@Overridepublic String getPassword() {return id_et_password.getText().toString();}@Overridepublic void clearUserName() {id_et_username.setText("");}@Overridepublic void clearPassword() {id_et_password.setText("");}@Overridepublic void toMainActivity(User user) {Toast.makeText(getApplicationContext(), user.getUsername() + "--登录成功", Toast.LENGTH_SHORT).show();}@Overridepublic void showFailedError() {Toast.makeText(getApplicationContext(), "登录失败", Toast.LENGTH_SHORT).show();}@Overridepublic void showLoading() {id_progressbar.setVisibility(View.VISIBLE);}@Overridepublic void hideLoading() {id_progressbar.setVisibility(View.INVISIBLE);}}
presenter包
/*** 这就是传说中的Prestener,这里面封装的都是Activity中复杂的业务逻辑* @author 白乾涛*/public class UserLoginPresenter {private IUserBiz userBiz;private IUserLoginView userLoginView;private Handler mHandler = new Handler() {public void handleMessage(android.os.Message msg) {};};//在构造Prestener时,需要传递一个IUserLoginView接口的实例(其实就是Activity),只有这样,Prestener才能对此实例进行操作public UserLoginPresenter(IUserLoginView userLoginView) {this.userBiz = new UserBiz();this.userLoginView = userLoginView;}public void login() {userLoginView.showLoading();//为了更具扩展性及进一步解耦,具体的登录逻辑又通过同样的方式转移到了IUserBiz接口上(统一放在biz包下)userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() {@Overridepublic void loginSuccess(final User user) {//需要再UI线程执行mHandler.post(new Runnable() {@Overridepublic void run() {userLoginView.toMainActivity(user);userLoginView.hideLoading();}});}@Overridepublic void loginFailed() {//需要在UI线程执行mHandler.post(new Runnable() {@Overridepublic void run() {userLoginView.showFailedError();userLoginView.hideLoading();}});}});}public void clear() {userLoginView.clearPassword();userLoginView.clearUserName();}}
bean包
/*** 一个业务bean,所有需要被操作的基本元素(不包括View)都应该定义在这里* @author 白乾涛*/public class User {private String username;private String password;public String getUsername() {return username;}public String getPassword() {return password;}public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}}
biz(业务)包
/*** 复杂的业务逻辑在这里定义:如,登录、忘记密码、联系客服* @author 白乾涛*/public interface IUserBiz {public void login(String username, String password, OnLoginListener onLoginListener);}/*** 复杂业务逻辑的具体实现:如具体的登录代码在这里编写* 这里面有一个回调* @author 白乾涛*/public class UserBiz implements IUserBiz {@Overridepublic void login(final String username, final String password, final OnLoginListener onLoginListener) {new Thread() {@Overridepublic void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if ("username".equals(username) && "password".equals(password)) {User user = new User();user.setUsername(username);user.setPassword(password);//成功时的回调onLoginListener.loginSuccess(user);} else {//失败时的回调onLoginListener.loginFailed();}}}.start();}}
/*** 这个其实不算是MVP中的东西(但一般都会有),这是一个回调,当执行复杂逻辑的同时做一些回调处理* @author 白乾涛*/public interface OnLoginListener {public void loginSuccess(User user);public void loginFailed();}
MVP模式 详解 案例的更多相关文章
- Javascript设计模式之装饰者模式详解篇
一.前言: 装饰者模式(Decorator Pattern):在不改变原类和继承的情况下动态扩展对象功能,通过包装一个对象来实现一个新的具有原对象相同接口的新的对象. 装饰者模式的特点: 1. 在不改 ...
- Extjs MVC开发模式详解
Extjs MVC开发模式详解 在JS的开发过程中,大规模的JS脚本难以组织和维护,这一直是困扰前端开发人员的头等问题.Extjs为了解决这种问题,在Extjs 4.x版本中引入了MVC开发模式, ...
- JavaScript严格模式详解
转载自阮一峰的博客 Javascript 严格模式详解 作者: 阮一峰 一.概述 除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict m ...
- HTTP协议头部与Keep-Alive模式详解
HTTP协议头部与Keep-Alive模式详解 .什么是Keep-Alive模式? 我们知道HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器 ...
- (" use strict")Javascript 严格模式详解
Javascript 严格模式详解 转载别人的博客内容,浏览了一遍,没有全部吸收,先保存一下链接 http://www.ruanyifeng.com/blog/2013/01/javascript_s ...
- HTTP协议Keep-Alive模式详解
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp22 HTTP协议Keep-Alive模式详解 1.什么是Keep-Aliv ...
- Java开源生鲜电商平台-盈利模式详解(源码可下载)
Java开源生鲜电商平台-盈利模式详解(源码可下载) 该平台提供一个联合买家与卖家的一个平台.(类似淘宝购物,这里指的是食材的购买.) 平台有以下的盈利模式:(类似的平台有美菜网,食材网等) 1. 订 ...
- ext.js的mvc开发模式详解
ext.js的mvc开发模式详解和环境配置 在JS的开发过程中,大规模的JS脚本难以组织和维护,这一直是困扰前端开发人员的头等问题.Extjs为了解决这种问题,在Extjs 4.x版本中引入了MVC开 ...
- Docker Kubernetes Service 网络服务代理模式详解
Docker Kubernetes Service 网络服务代理模式详解 Service service是实现kubernetes网络通信的一个服务 主要功能:负载均衡.网络规则分布到具体pod 注 ...
随机推荐
- [置顶] Spring的DI依赖实现分析
DI(依赖注入)是Spring最底层的核心容器要实现的功能之一,利用DI可以实现程序功能的控制反转(控制反转即程序之间之间的依赖关系不再由程序员来负责,而是由Spring容器来负责) 一个简单的例子( ...
- work登录页
- 跨域的iframe自动调整高度(cross-domain iframe resizer)
可以使用iframe-resizer项目地址: http://davidjbradshaw.github.io/iframe-resizer/演示地址: http://davidjbradshaw.c ...
- ubuntu忘记登录账户以及密码
笔者在诸多方面仍然是初学者.感兴趣的方面也很多,电脑装上ubuntu14.04也有一段时间了,但仍然在不断学习更多基础的东西. 因为对于命令行界面还有些不习惯,所以一直依赖于图形界面,需要使用终端的时 ...
- HTML5手机开发——滚动和惯性缓动
1. 滚动 以下是三种实现方式: 1) 利用原生的css属性 overflow: scroll div id= parent style = overflow:scroll; divid='conte ...
- COUNT()函数的使用
COUNT函数 让我们能够数出在表格中有多少笔资料被选出来.它的语法是: SELECT COUNT("栏位名") FROM "表格名" 举例来说, ...
- PHP进度条
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- C语言基础学习基本数据类型-浮点型
float和double 加了小数点的数都是浮点数.C语言有两种书写浮点数的方式,一种是使用常用的标准小数点表示法,如下: 0.00056 8.0 1.23 第二种表示浮点值叫做E表示法.下面是一些例 ...
- 以k个元素为一组反转单链表
Example: input: 1->2->3->4->5->6->7->8->NULL and k = 3 output:3->2->1- ...
- CSU 1160(进制问题)
CSU 1160 Time Limit:1000MS Memory Limit:131072KB 64bit IO Format:%lld & %llu Descrip ...

