MVP架构模式
- 概念解释
- MVP是Model(数据) View(界面) Presenter(表现层)的缩写,它是MVC架构的变种,强调Model和View的最大化解耦和单一职责原则
- Model:负责数据的来源和封装,比如网络请求类,数据库操作类以及java bean,如果有必要则提供接口暴露自己处理数据的状态和进度。
- View:负责UI相关,如布局UI的初始化,各种listener的设置。在Android中,我们通常写的Activity和Fragment就是属于View层;在web开发中,html则是View层。
- Controller:业务逻辑控制器,主要负责当获取到数据后对数据进行逻辑处理,然后将数据绑定到View上;比如:请求一个url,从网络获取到数据,进行解析javabean,然后各种set数据。对于控制器的概念大家很好理解,因为我们每天都在这样做,在Activity中请求数据然后更新UI。但是结合View的概念来看,很显然Activity和Fragment不但承担了View的任务,还负责完成的Controller的功能,随着业务功能的增多,Activity的代码越来越难以阅读和维护,这就是在Android中使用MVC的弊端,为了解决MVC模式下View层的臃肿,MVP模式应运而生。
- Presenter:专门从C独立出来的业务逻辑层,主要负责处理原先View层的业务逻辑,解决了Activity的臃肿问题,让Activity只负责处理UI,职责更加明确;并且将View层的业务逻辑抽取到P层之后,View层与Model层也实现了解耦;便于后期代码的扩展和维护,并且业务逻辑层独立后代码还得到很大的重用性
- 总结:MVC模式下,V和C纠缠不清,并且View和Model相互关联,而MVP模式下Model和VIew解耦,便于单元测试,项目维护,代码重用
先看看一个登录界面的业务逻辑和UI更新全部写在Activity的代码:
public class LoginActivity extends ActionBarActivity implements OnClickListener{
EditText etUsername,etPassword;
Button btn_login;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etUsername = (EditText) findViewById(R.id.et_username);
etPassword = (EditText) findViewById(R.id.et_password);
btn_login = (Button) findViewById(R.id.btn_login); //设置点击事件
btn_login.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_login:
String username = etUsername.getText().toString();
String password = etPassword.getText().toString(); if(checkInput(username,password)){
//提交登录
//执行登录请求
execLogin(username, password);
} break;
}
}
//执行登录请求
public void execLogin(String username,String password){
//执行登录请求的伪代码
HttpHelper helper = new HttpHelper();
helper.execRequest("http://www.baidu.com", new HttpCallback() {
@Override
public void onSuccess() {
//提示登录成功
showLoginSuccess(LoginActivity.this); //保存登录相关数据,如登录的标记,用户的唯一标识
saveLoginData();
}
@Override
public void onFail() {
//关闭登录对话框
hideLoginDialog(LoginActivity.this);
//提示登录失败
showLoginFail(LoginActivity.this);
}
});
}
//保存登录数据
public void saveLoginData(){
//保存登录相关的数据,代码略过...
}
//提示登录成功
public void showLoginFail(Context context){
Toast.makeText(context, "登录失败", 0).show();
}
//提示登录失败
public void showLoginSuccess(Context context){
Toast.makeText(context, "登录成功", 0).show();
}
//检查输入的合法性
private boolean checkInput(String username, String password) {
boolean result = true;
//1.检查为空
if(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)){
Toast.makeText(this, "用户名或者密码不能为空!", 0).show();
result = false;
}
//2.检查长度
if(username.length()!=11){
Toast.makeText(this, "用户名长度不正确!", 0).show();
result = false;
}
if(password.length()<5){
Toast.makeText(this, "密码长度不能小于5位!", 0).show();
result = false;
}
return result;
}
}现在抽取出LoginPresenter类,如下:
/**
* 业务逻辑封装层
* @author lxj
*
*/
public class LoginPresenter {
private ILoginView loginView; /**
* 生命周期相关方法
*/
public void onDestory(){
//do something to release and avoid memory leak;
}
public void onStart(){
//do something when onStart
}
public void onStop(){
//do something when onStop
}
public void onResume(){
//do something when onResume
}
public void onPause(){
//do something when onPause
} public LoginPresenter(ILoginView loginView){
this.loginView = loginView;
}
//登录的方法
public void login(String username, String password) {
if(!checkInput(username, password)){
return;
}
// 执行登录请求的伪代码
HttpHelper helper = new HttpHelper();
helper.execRequest("http://www.baidu.com", new HttpCallback() {
@Override
public void onSuccess() {
// 需要UI展示,暴露接口
loginView.showLoginSuccess();
// 保存登录相关数据,如登录的标记,用户的唯一标识
saveLoginData();
}
@Override
public void onFail() {
// 需要UI展示,暴露接口
loginView.showLoginFail();
}
});
}
private void saveLoginData() {
//do something
}
// 检查输入的合法性
private boolean checkInput(String username, String password) {
boolean result = true;
// 1.检查为空
if (TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {
loginView.showInputNoNull();
result = false;
}
// 2.检查长度
if (username.length() != 11) {
loginView.showUsernameLengthError();
result = false;
}
return result;
}
}View和P解耦接口如下ILoginView:
public interface ILoginView {
void showLoginSuccess();
void showLoginFail();
void showInputNoNull();
void showUsernameLengthError();
}最后的View层编写如下:
public class LoginActivity extends Activity implements OnClickListener,ILoginView{
EditText etUsername,etPassword;
Button btn_login;
private LoginPresenter loginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etUsername = (EditText) findViewById(R.id.et_username);
etPassword = (EditText) findViewById(R.id.et_password);
btn_login = (Button) findViewById(R.id.btn_login);
//设置点击事件
btn_login.setOnClickListener(this);
//与loginPresenter交互
loginPresenter = new LoginPresenter(this); }
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_login:
String username = etUsername.getText().toString();
String password = etPassword.getText().toString();
loginPresenter.login(username,password);
break;
}
}
public void showLoginSuccess(){
Toast.makeText(this, "登录成功", 0).show();
}
public void showLoginFail(){
Toast.makeText(this, "登录失败", 0).show();
}
public void showInputNoNull(){
Toast.makeText(this, "用户名和密码不能为空!", 0).show();
}
public void showUsernameLengthError(){
Toast.makeText(this, "用户名长度不正确!", 0).show();
}
public void hideLoginDialog(){
if(progressDialog!=null){
progressDialog.dismiss();
}
} @Override
protected void onResume() {
super.onResume();
loginPresenter.onResume();
}
@Override
protected void onStart() {
super.onStart();
loginPresenter.onStart();
}
@Override
protected void onStop() {
super.onStop();
loginPresenter.onStop();
} @Override
protected void onPause() {
super.onPause();
loginPresenter.onPause();
} @Override
protected void onDestroy() {
super.onDestroy();
loginPresenter.onDestory();
}
}总结:MVP只是给我们提出了分层解耦的思想,并没有一个固定的实现。Google虽然出了官方的MVP实现示例,但是并没有太多人去跟随,很多公司在对Presenter层都有自己的理解,此处的案例相对来说比较规范,对MVP三层都有清晰的解耦和实现,在茫茫开源项目中,算是比较好的容易理解的上手项目了。
MVP架构模式的更多相关文章
- 用户登录(Material Design + Data-Binding + MVP架构模式)实现
转载请注明出处: http://www.cnblogs.com/cnwutianhao/p/6772759.html MVP架构模式 大家都不陌生,Google 也给出过相应的参考 Sample, 但 ...
- iOS - MVP 架构模式
1.MVP 从字面意思来理解,MVP 即 Modal View Presenter(模型 视图 协调器),MVP 实现了 Cocoa 的 MVC 的愿景.MVP 的协调器 Presenter 并没有对 ...
- 设计模式笔记之一:MVP架构模式入门(转)
写在前面:昨天晚上,公司请来专家讲解了下MVP,并要求今后各自负责的模块都要慢慢的转到MVP模式上来.以前由于能力有限,没有认真关注过设计模式.框架什么的,昨晚突然兴趣大发,故这两天空闲时间一直在学习 ...
- 死磕安卓前序:MVP架构探究之旅—基础篇
前言 了解相关更多技术,可参考<我就死磕安卓了,怎么了?>,接下来谈一谈我们来学习一下MVP的基本认识. 大家对MVC的架构模式再熟悉不过.今天我们就学习一下MVP架构模式. MVC和MV ...
- Android MVP开发模式及Retrofit + RxJava封装
代码已上传到Github,因为接口都是模拟无法进行测试,明白大概的逻辑就行了! 欢迎浏览我的博客--https://pushy.site 1. MVP模式 1.1 介绍 如果熟悉MVP模式架构的话,对 ...
- iOS 架构模式--解密 MVC,MVP,MVVM以及VIPER架构
本文由CocoaChina译者lynulzy(社区ID)翻译 作者:Bohdan Orlov 原文:iOS Architecture Patterns 在 iOS 中使用 MVC 架构感觉很奇怪? 迁 ...
- 浅谈MVC、MVP、MVVM架构模式的区别和联系
MVC.MVP.MVVM这些模式是为了解决开发过程中的实际问题而提出来的,目前作为主流的几种架构模式而被广泛使用. 一.MVC(Model-View-Controller) MVC是比较直观的架构模式 ...
- MVC、MVCS、MVVM、MVP、VIPER等这么多架构模式哪一个好呢?
在项目开启阶段,其中一个很重要的环节就是选架构. 那么面对目前已知的这么多架构模式我们该怎么选择呢?这确实是个很让人头疼的问题! 下面我就在这里梳理一下目前常见的一些架构模式. 先逐个对它们的分析 ...
- 浅谈MVP架构及开发模式
Model-View-Presenter(MVP)概述 MVC模式已经出现了几十年了,在GUI领域已经得到了广泛的应用,由于微软ASP.NET MVC Framework的出现,致使MVC一度成 ...
随机推荐
- centos中w使用smbclient连接window出现:session setup failed: NT_STATUS_LOGON_FAILURE
1. 在window中网络->我自己的电脑->能够查看到共享文件,说明window的共享是正常了; 2. 在window中配置共享时,使用的是仅仅同意超级管理员訪问,可是我把超级管理员改名 ...
- CxImage的编译及简单使用举例
1. 从http://sourceforge.net/projects/cximage/下载最新的CxImage 702源代码. 2. 解压缩后,以管理员身份打开CxImageFull_vc10. ...
- Zookeeper 简单操作
1. 连接到zookeeper服务 [java2000_wl@localhost zookeeper-3]$ bin/zkCli.sh -server 127.0.0.1:2181 也可以连接远端的 ...
- 解决运行scrapy是报错No module named cryptography,解决cryptography的安装问题,解决libffi的安装问题
在linux下配置完运行是出现ImportError: No module named cryptography.hazmat.bindings.openssl.binding的错误.原因是crapt ...
- 嵌入式开发之命令行---linux下的find文件查找命令与grep文件内容查找命令
在使用linux时,经常需要进行文件查找.其中查找的命令主要有find和grep.两个命令是有区的. 区别:(1)find命令是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访 ...
- oracle sql 超长报ORA-01460错误
程序查找数据的时候报错了: ORA-01460: 转换请求无法实施或不合理 这是什么鬼?不合理你就提嘛,报错干什么. 程序原本好好的,现在突然报错了.数据库并没有什么更改. 后来猜测是因为执行的SQL ...
- asp.net mvc + javascript生成下载文件
近期做的是对现有项目进行重构.WEB FROM改成MVC,其实也算是推倒重来了. 里面有一个导出功能,将数据输出成txt文件,供下载.原先的做法是有一个隐藏的iframe,在这个iframe的页面中设 ...
- 命令行方式下登录SqlPlus,密码含特殊字符
全撞上了! 真难侍候!oracle 12c,想登录sql plus,结果没有图形界面,直接出来个命令行.这下好了,我这个数据库,多实例,意味着登录要指定实例:密码中含有特殊字符"@" ...
- YTU 1001: A+B Problem
1001: A+B Problem 时间限制: 1 Sec 内存限制: 10 MB 提交: 4864 解决: 3132 [提交][状态][讨论版] 题目描述 Calculate a+b 输入 Tw ...
- linux永久或临时修改dns
1.临时修改网卡DNS地址 sudo vim /etc/resolv.conf 改为如下内容: nameserver 8.8.8.8 #修改成你的主DNS nameserver 8.8.4.4 #修改 ...