MVP模式入门案例
随着UI创建技术的功能日益增强,UI层也履行着越来越多的职责。为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数据的可视化以及与用户的交互,同时让Model只关系数据的处理,基于MVC概念的MVP(Model-View-Presenter)模式应运而生。
四个要素:
为什么使用MVP模式
在Android开发中,Activity并不是一个标准的MVC模式中的Controller,它的首要职责是加载应用的布局和初始化用户界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。当我们将其中复杂的逻辑处理移至另外的一个类(Presneter)中时,Activity其实就是MVP模式中View,它负责UI元素的初始化,建立UI元素与Presenter的关联(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由Presenter处理).
另外,回想一下你在开发Android应用时是如何对代码逻辑进行单元测试的?是否每次都要将应用部署到Android模拟器或真机上,然后通过模拟用户操作进行测试?然而由于Android平台的特性,每次部署都耗费了大量的时间,这直接导致开发效率的降低。而在MVP模式中,处理复杂逻辑的Presenter是通过interface与View(Activity)进行交互的,这说明了什么?说明我们可以通过自定义类实现这个interface来模拟Activity的行为对Presenter进行单元测试,省去了大量的部署及测试的时间。
MVP与MVC的异同
MVC模式与MVP模式都作为用来分离UI层与业务层的一种开发模式被应用了很多年。在我们选择一种开发模式时,首先需要了解一下这种模式的利弊:
无论MVC或是MVP模式都不可避免地存在一个弊端:额外的代码复杂度及学习成本。
这就导致了这两种开发模式也许并不是很小型应用。
(1)降低耦合度(2)模块职责划分明显(3)利于测试驱动开发(4)代码复用(5)隐藏数据(6)代码灵活性
步骤
- 首先完成User Been文件的创建,在这里面,我们只需要要User的serget方法。
- 接着思考User有什么业务,并将这些业务统统添加进入IUserBiz接口中。
- 每一个业务逻辑都有一个附带的Listener,这个Listener中有执行这个业务后会发生的事情。
- 然后UserBiz 将 IUserBiz中的功能实现。
- 对应的View(Activity)中的功能写一个 接口出来。
- 对应的View(Activity)实现接口。
- 实现Presenter,Presenter的作用就是将View与Model进行连接。
步骤一 User Been的创建
仔细看我上面那个登录界面,然后回答:
- 根据上面的图片如果是你创建一个User,里面有什么属性?
然后你想象我们有登录与清除的功能,那你的User中需要有什么方法?
• public class User {
private String username ;
private String password ; public String getUsername()
{
return username;
} public void setUsername(String username)
{
this.username = username;
} public String getPassword()
{
return password;
} public void setPassword(String password)
{
this.password = password;
}
步骤二 IUserBiz接口的创建
思考:我们已经有一个User Been了,我们需要用这个User进行什么操作?并将User即将进行的操作写为抽象方法。
public interface IUserBiz {
public void login(String username, String password, OnLoginListener loginListener);
}
步骤三 附带的Listener创建
思考:我们之前创建的IUserBiz接口中的方法有哪种情况会发生?并将可能会出现的情况进行写入抽象Listener中去。
public interface OnLoginListener {
void loginSuccess(User user);
void loginFailed();
}
步骤四 创建UserBiz直接实现IUserBiz
就是将方法实现
public class UserBiz implements IUserBiz {
@Override
public void login(final String username, final String password, final OnLoginListener loginListener) {
//模拟子线程耗时操作
new Thread() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//模拟登录成功
if ("123".equals(username) && "123".equals(password)) {
User user = new User();
user.setUsername(username);
user.setPassword(password);
loginListener.loginSuccess(user);
} else {
loginListener.loginFailed();
}
}
}.start();
}
}
步骤六 将View(Activity)连接创建好的接口并实现
根据接口并实现
public class UserLoginActivity extends ActionBarActivity implements IUserLoginView {
private EditText mEtUsername, mEtPassword;
private Button mBtnLogin, mBtnClear;
private ProgressBar mPbLoading; private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_login); initViews();
} private void initViews() {
mEtUsername = (EditText) findViewById(R.id.id_et_username);
mEtPassword = (EditText) findViewById(R.id.id_et_password); mBtnClear = (Button) findViewById(R.id.id_btn_clear);
mBtnLogin = (Button) findViewById(R.id.id_btn_login); mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading); mBtnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mUserLoginPresenter.login();
}
}); mBtnClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mUserLoginPresenter.clear();
}
});
} @Override
public String getUserName() {
return mEtUsername.getText().toString();
} @Override
public String getPassword() {
return mEtPassword.getText().toString();
} @Override
public void clearUserName() {
mEtUsername.setText("");
} @Override
public void clearPassword() {
mEtPassword.setText("");
} @Override
public void showLoading() {
mPbLoading.setVisibility(View.VISIBLE);
} @Override
public void hideLoading() {
mPbLoading.setVisibility(View.GONE);
} @Override
public void toMainActivity(User user) {
Toast.makeText(this, user.getUsername() +
" login success , to MainActivity", Toast.LENGTH_SHORT).show();
} @Override
public void showFailedError() {
Toast.makeText(this,
"login failed", Toast.LENGTH_SHORT).show();
步骤七 实现Presenter
在MVP中Presenter将Model与View进行一个连接,在这个地方的Presenter属于一个中间人的传话的效果。
那么在这个Presenter类中,主要就是图中Button的方法,也就是一个login方法,一个clear方法,具体实现还是将之前所实现的接口进行一个方法对接。
//将**View**与**Model**之间进行操作。
public class UserLoginPresenter {
private IUserBiz userBiz;
private IUserLoginView userLoginView;
private Handler mHandler = new Handler();
////传递一个loginView
public UserLoginPresenter(IUserLoginView userLoginView) { //这个是View的代表
this.userLoginView = userLoginView;
//这个是Model的代表
this.userBiz = new UserBiz();
}
//下面有两个方法主要是将两个**Button**的操作直接封装完成,然后直接使用
public void login() {
userLoginView.showLoading();
userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() {
@Override
public void loginSuccess(final User user) {
//需要在UI线程执行
mHandler.post(new Runnable() {
@Override
public void run() {
userLoginView.toMainActivity(user);
userLoginView.hideLoading();
}
}); } @Override
public void loginFailed() {
//需要在UI线程执行
mHandler.post(new Runnable() {
@Override
public void run() {
userLoginView.showFailedError();
userLoginView.hideLoading();
}
}); }
});
}
// //这个是clear按钮
public void clear() {
userLoginView.clearUserName();
userLoginView.clearPassword();
} }
解答
一 User Been的创建
仔细看我上面那个登录界面,然后回答:
- 根据上面的图片如果是你创建一个User,里面有什么属性?
- 然后你想象我们有登录与清除的功能,那你的User中需要有什么方法?
回答:
1.User有userName与password两个属性。
2.userName与password拥有setget方法即可。
二 IUserBiz接口的创建
思考:我们已经有一个User Been了,我们需要用这个User进行什么操作?
并将User即将进行的操作写为抽象方法。
回答:
User需要有一个login的功能,这个功能中我们需要将我们的账号密码传递进
去,同时还有一个Listener需要监听login的情况,在下面就是Listener的创
建了。
三 附带的Listener创建
思考:我们之前创建的IUserBiz接口中的方法有哪种情况会发生?
并将可能会出现的情况进行写入抽象Listener中去。
回答:
以前接口中主要实现了一个login的功能,这个功能会有两种可能发生,第一
种就是登录成功,第二种就是登录失败。
四 创建UserBiz直接实现IUserBiz
就是将方法实现。
五 将View(Activity)中的功能写入接口
仔细看我上面那个登录界面,然后回答:
- Activity中有两个Button,点击一下会进行什么操作?
- 操作过程中会发生什么情况,并将情况转换成对应的方法。
回答:
1.点击login会有登录成功或者登录失败,在这里登录需要获取Edit的信息。
2.点击clear会清除EditView。
那么方法如下:
登录成功方法
登录失败方法
获取UserName
获取PassWord
清除Edit框
六 将View(Activity)连接创建好的接口并实现
根据接口并实现。
七 实现Presenter
在MVP中Presenter将Model与View进行一个连接,在这个地方的Presenter属于一个中间人的传话的效果。
那么在这个Presenter类中,主要就是图中Button的方法,也就是一个login方法,一个clear方法,具体实现还是将之前所实现的接口进行一个方法对接。
MVP模式入门案例的更多相关文章
- MVP模式入门(结合Rxjava,Retrofit)
本文MVP的sample实现效果: github地址:https://github.com/xurui1995/MvpSample 老规矩,在说对MVP模式的理解之前还是要再谈谈MVC模式,了解了MV ...
- Android开发学习--MVP模式入门
1.模型与视图完全分离,我们可以修改视图而不影响模型2.可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部3.我们可以将一个Presenter用于多个视图,而不需要改变Pr ...
- MVC模式入门案例
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widg ...
- Mybatis入门案例中设计模式的简单分析
Talk is cheap, show me the code! public class TestMybatis { public static void main(String[] args) t ...
- 设计模式笔记之一:MVP架构模式入门(转)
写在前面:昨天晚上,公司请来专家讲解了下MVP,并要求今后各自负责的模块都要慢慢的转到MVP模式上来.以前由于能力有限,没有认真关注过设计模式.框架什么的,昨晚突然兴趣大发,故这两天空闲时间一直在学习 ...
- Android MVC,MVP,MVVM模式入门——重构登陆注册功能
一 MVC模式: M:model,业务逻辑 V:view,对应布局文件 C:Controllor,对应Activity 项目框架: 代码部分: layout文件(适用于MVC和MVP两个Demo): ...
- android MVP模式介绍与实战
android MVP模式介绍与实战 描述 MVP模式是什么?MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数 ...
- Nginx入门案例(Mac版)
Nginx(engine x)是一个轻量级.高性能的Web和反向代理服务器,也是一个IMAP.POP3和SMTP服务器,并且安装十分简单,配置文件非常简洁,启动特别容易,运行十分稳定,几乎可以做到7* ...
- jms - activeMQ入门案例
activeMQ入门案例 叨叨一波,很久没写博客了,最近比较慢,时间抽不出来,这个借口说的很尴尬...我知道作为一名合格的码农就必须养成每天一博客的习惯.希望友友们别像我这样懒,闲话不多时进入今天的主 ...
随机推荐
- cpp编码规范要求
1.所有头文件使用#ifndef #define #endif来防止文件被多重包含,命名格式当是: <PROJECT>_<PATH>_<FILE>_H_ 2.只有当 ...
- ScrollView 滚动视图
ScrollView 种类: 1.HorizontalScrollView:水平滚动视图 2.ScrollView:垂直滚动视图(常用类) public class MainActivity exte ...
- 使用 Eclipse 构建的时候会出现 run as 中没有 maven package 选项
注:该方法来自我学习时别人分享的出现问题的解决方法,并没有亲自测试,仅供参考 是因为建的是普通 java 工程,需要把它转换成 maven project. 1.右键工程--maven--Disabl ...
- C/C++小课之数组名是什么
我们今天讨论数组名是什么东西,理解它有助于我们进一步理解和使用指针. 因为它涉及到了内存地址. 问题 数组名是什么?含义是什么? 思路 前提 一个值+1之后的变化可以反映出它的意义/含义. 前提的证明 ...
- sql 181. 超过经理收入的员工
Employee 表包含所有员工,他们的经理也属于员工.每个员工都有一个 Id,此外还有一列对应员工的经理的 Id. +----+-------+--------+-----------+| Id | ...
- 网络资源url转化为file对象下载文件
注:只测试过网络图片资源. 一.使用org.apache.commons.io.FileUtils 二. 三.httpURLConnection.disconnect(); 四. import org ...
- solr 数据库关联,表数据添加不进solr,一直indexing
id没有映射,数据库表字段没有id,要把其中一字段映射为id
- 微信退款SpringBoot读取resource下的证书
微信支付退款接口,需要证书双向验证,测试的时候证书暂时放在resource下,上图 起初MyConfig中我是这样,在本机IDE中运行没有问题 但到Linux服务器的docker中运行就IO异常了,查 ...
- 关于JavaScript的事件绑定
js事件绑定的几种方式 JavaScript中有三种常用的绑定事件方法: 1. 在DOM元素中直接绑定: 2. 在JavaScript代码中绑定: 3. 绑定事件佳妮婷函数. 一.在DOM元素中直接绑 ...
- 快速数论变换NTT模板
51nod 1348 乘积之和 #include <cmath> #include <iostream> #include <cstdio> #include &l ...