## (一).前言:
今天我们的项目继续更新,今天我们主要讲解MVP开发模式以及具体实例。
FastDev4Android框架项目地址:[https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android)
## (二).简介:
MVP(Model ViewPresenter)模式是著名的MVC(Model ViewController)模式的一个演化版本,目前它在Android应用开发中越来越重要了。初看起来我们会感觉增加了很多类接口代码看起来更加清晰。
MVP模式可以分离显示层和逻辑层,所以功能接口如何工作与功能的展示可以实现分离,MVP模式理想化地可以实现同一份逻辑代码搭配不同的显示界面。不过MVP不是一个结构化的模式,它只是负责显示层而已,任何时候都可以在自己的项目结构中使用MVP模式。(不局限于Android项目开发)
因为MVP其实就是从MVC模式演化产生的,那么我们先看一下著名的MVC模式:
* View:对应于布局文件
* Model:业务逻辑和实体模型
* Controller:控制器,Android中对应于Activity
对应的交互图如下:
![](https://box.kancloud.cn/2016-01-18_569c8eb2e03bb.jpg)
虽然Android系统应用开发本身是遵循MVC开发模式的,但是我们仔细看一下View层和Activity,具体view布局文件中的数据绑定和事件处理的方法代码都是冗余在Activity中的,所以我们经常看可以看到Activity类动不动就是少则九百行,多则上千甚至几千行。那么现在的演化升级版本的MVP的模式又是怎么样的呢?MVP模式会引入 Presenter层,该机型复杂完成View层和Model层的交互,那么具体MVP对应如下:
* View:View通常来说是由Activity实现的,它会包含一个Presenter的引用,View要做的就只是在每次有接口调用的时候(比如按钮点击后)调用Presenter的方法。
* Model:业务逻辑和实体模型
* Presenter:主要作为沟通View和Model的桥梁,它从Model层检索数据后,返回给View层,但是不像MVC结构,因为它也可以决定与View层的交互操作。
数据交互图如下:
![](https://box.kancloud.cn/2016-01-18_569c8eb2f041e.jpg)
观察上面两个模式的交互图,是不是MVP模式更加清晰简单啊!
## (三).MVC和MVP区别:
我们来具体看一下下面两张对比,就可以看来具体区别了:
![](https://box.kancloud.cn/2016-01-18_569c8eb314fec.jpg)
观察上图我们可以发现MVP模式中,View和Model的交互是通过Presenter来进行完成,这样统一管理,逻辑会更加清晰。
## (四).MVP模式例子讲解:
4.1.具体实现功能需求:我们是用MVP模式来进行实现用户登录操作.
4.2.例子实例如下:
![](https://box.kancloud.cn/2016-01-18_569c8eb33930e.jpg)
4.3.项目代码框架如下:
![](https://box.kancloud.cn/2016-01-18_569c8eb3c006b.jpg)
![](https://box.kancloud.cn/2016-01-18_569c8eb3d2e73.jpg)
![](https://box.kancloud.cn/2016-01-18_569c8eb3e0957.jpg)
![](https://box.kancloud.cn/2016-01-18_569c8eb3f226f.jpg)
4.4.代码具体实现:
4.4.1.Model层:Bean类(Entity),PersonBean类,然后在业务逻辑类中有登录方法,同时把登录成功状态回调接口传入进入,具体如下:
~~~
packagecom.chinaztt.fda.entity;
/**
* 当前类注释:用户信息实体类
* 项目名:FastDev4Android
* 包名:com.chinaztt.fda.entity
* 作者:江清清 on 15/10/27 14:13
* 邮箱:jiangqqlmj@163.com
* QQ: 781931404
* 公司:江苏中天科技软件技术有限公司
*/
public class PersonBean {
private String username;
private String password;
public PersonBean() {
}
public PersonBean(String username, Stringpassword) {
this.username = username;
this.password = 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;
}
@Override
public String toString() {
return "PersonBean{" +
"username='" +username + '\'' +
", password='" +password + '\'' +
'}';
}
}
~~~
~~~
public interface IPersonBiz {
void login(String username,Stringpassword,LoginRequestCallBack valueCallBack);
}
~~~
~~~
packagecom.chinaztt.fda.biz.imp;
importcom.chinaztt.fda.biz.IPersonBiz;
importcom.chinaztt.fda.biz.LoginRequestCallBack;
importcom.chinaztt.fda.entity.PersonBean;
importcom.chinaztt.fda.utils.Log;
/**
* 当前类注释:用户相关业务逻辑实现类
* 项目名:FastDev4Android
* 包名:com.chinaztt.fda.biz.imp
* 作者:江清清 on 15/10/27 16:33
* 邮箱:jiangqqlmj@163.com
* QQ: 781931404
* 公司:江苏中天科技软件技术有限公司
*/
public class PersonBizImp implements IPersonBiz{
private static final String TAG="PersonBizImp";
@Override
public void login(final String username,final String password, final LoginRequestCallBack valueCallBack) {
Log.d(TAG,"username:"+username+",password:"+password);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(4500);
} catch (InterruptedExceptione) {
e.printStackTrace();
}
//进行开始登录,这边应该进行请求服务器,进行数据验证
if(username.equals("jiangqq")&&password.equals("12345")){
valueCallBack.loginSuccess(new PersonBean(username,password));
}else{
valueCallBack.loginFailed();
}
}
}).start();
}
}
~~~
~~~
packagecom.chinaztt.fda.biz;
importcom.chinaztt.fda.entity.PersonBean;
/**
* 当前类注释:登录请求结果回调
* 项目名:FastDev4Android
* 包名:com.chinaztt.fda.biz
* 作者:江清清 on 15/10/27 19:50
* 邮箱:jiangqqlmj@163.com
* QQ: 781931404
* 公司:江苏中天科技软件技术有限公司
*/
public interface LoginRequestCallBack {
//登录成功回调方法
void loginSuccess(PersonBean personBean);
//登录失败回调方法
void loginFailed();
}
~~~
4.4.2.View层:该通过Presenter与View进行交互,这边需要定义一个接口ILoginView:
~~~
packagecom.chinaztt.fda.ui.view;
importcom.chinaztt.fda.entity.PersonBean;
/**
* 当前类注释:登录页面 相关操作 功能接口
* 项目名:FastDev4Android
* 包名:com.chinaztt.fda.ui.view
* 作者:江清清 on 15/10/27 16:35
* 邮箱:jiangqqlmj@163.com
* QQ: 781931404
* 公司:江苏中天科技软件技术有限公司
*/
public interface ILoginView {
//获取用户名
String getUserName();
//获取密码
String getPassword();
void showSuccessInfo(PersonBeanpersonBean);
void showFailedInfo();
}
~~~
有了上面的接口之后,我们就需要写我们的实现类Activity了,就非常简单了
~~~
packagecom.chinaztt.fda.test;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.widget.Button;
importandroid.widget.EditText;
importcom.chinaztt.fda.entity.PersonBean;
importcom.chinaztt.fda.presenter.LoginPresenter;
importcom.chinaztt.fda.ui.R;
importcom.chinaztt.fda.ui.base.BaseActivity;
importcom.chinaztt.fda.ui.view.ILoginView;
importcom.chinaztt.fda.utils.Log;
importorg.androidannotations.annotations.EActivity;
/**
* 当前类注释:MVP开发模式实例
* 项目名:FastDev4Android
* 包名:com.chinaztt.fda.test
* 作者:江清清 on 15/10/27 13:38
* 邮箱:jiangqqlmj@163.com
* QQ: 781931404
* 公司:江苏中天科技软件技术有限公司
*/
@EActivity
public class MVPTestActivity extends BaseActivity implements ILoginView{
private static final String TAG="MVPTestActivity";
private EditText ed_username;
private EditText ed_password;
private Button btn_login;
private LoginPresenter mLoginPresenter;
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mvp_test_layout);
ed_username=(EditText)this.findViewById(R.id.ed_username);
ed_password=(EditText)this.findViewById(R.id.ed_password);
btn_login=(Button)this.findViewById(R.id.btn_login);
mLoginPresenter=newLoginPresenter(this);
btn_login.setOnClickListener(newView.OnClickListener() {
@Override
public void onClick(View v) {
mLoginPresenter.loginSystem();
}
});
}
/**
* 进行返回用户名信息
* @return
*/
@Override
public String getUserName() {
returned_username.getText().toString().trim();
}
/**
* 进行返回用户密码信息
* @return
*/
@Override
public String getPassword() {
returned_password.getText().toString().trim();
}
/**
* 登录成功 回调
* @param personBean
*/
@Override
public void showSuccessInfo(PersonBeanpersonBean) {
Log.d(TAG,"showSuccessInfo:"+personBean.toString());
showToastMsgShort("登录成功:"+personBean.toString());
}
/**
* 登录失败 回调
*/
@Override
public void showFailedInfo() {
Log.d(TAG,"showFailedInfo...");
showToastMsgShort("登录失败...");
}
}
~~~
最后还少一个交互桥梁Presenter:
4.4.3.Presenter层:作为Model和View之间的交互桥梁,在本例中进行执行登录操作,然后去Model业务中执行登录,最后把登录结果信息返回给View层,就是这么简单:
~~~
packagecom.chinaztt.fda.presenter;
importandroid.os.Handler;
importcom.chinaztt.fda.biz.IPersonBiz;
importcom.chinaztt.fda.biz.LoginRequestCallBack;
importcom.chinaztt.fda.biz.imp.PersonBizImp;
importcom.chinaztt.fda.entity.PersonBean;
importcom.chinaztt.fda.ui.view.ILoginView;
importcom.chinaztt.fda.utils.Log;
/**
* 当前类注释:负责完成登录界面View于Model(IPersonBiz)间的交互
* 项目名:FastDev4Android
* 包名:com.chinaztt.fda.presenter
* 作者:江清清 on 15/10/27 16:36
* 邮箱:jiangqqlmj@163.com
* QQ: 781931404
* 公司:江苏中天科技软件技术有限公司
*/
public class LoginPresenter {
private static final String TAG="LoginPresenter";
private ILoginView mLoginView;
private IPersonBiz mPersonBiz;
private Handler mHandler=new Handler();
public LoginPresenter(ILoginView view) {
mLoginView = view;
mPersonBiz = new PersonBizImp();
}
public void loginSystem(){
mPersonBiz.login(mLoginView.getUserName(), mLoginView.getPassword(), newLoginRequestCallBack() {
/**
* 登录成功
* @param personBean
*/
@Override
public void loginSuccess(finalPersonBean personBean) {
Log.d(TAG,"登录成功:" + personBean.toString());
mHandler.post(new Runnable() {
@Override
public void run() {
mLoginView.showSuccessInfo(personBean);
}
});
}
/**
* 登录失败
*/
@Override
public void loginFailed() {
Log.d(TAG,"登录失败...");
mHandler.post(new Runnable() {
@Override
public void run() {
mLoginView.showFailedInfo();;
}
});
}
});
}
}
~~~
到此我们的MVP模式的例子就大体完成了,看一下上面的效果演示就OK了。
我们的项目已经配置集成了MVPDemo的例子.欢迎大家去Github站点进行clone或者下载浏览:[https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android) 同时欢迎大家star和fork整个开源快速开发框架项目~
- 前言
- Android快速开发框架介绍(一)
- Android首页图片自动无限循环轮播Gallery+FlowIndicator(二)
- Android 列表下拉刷新组件PullToRefreshListView使用(三)
- Android 数据缓存器ACache的详解和使用(四)
- Android崩溃异常捕捉CustomCrash,提升用户体验(五)
- Android实现沉浸式状态栏(六)
- AndroidAnnnotations注入框架介绍和Android Studios基本配置(七)
- AndroidAnnnotations注入框架的工作原理(八)
- AndroidAnnnotations注入框架使用之注入组件Components(九)
- AndroidAnnnotations注入框架使用之Injection标签详解(十)
- AndroidAnnnotations注入框架使用之事件绑定Event Binding(十一)
- AndroidAnnnotations注入框架使用之线程处理Threading(十二)
- AndroidAnnnotations注入框架使用之第三方框架集成RoboGuice(十三)
- AndroidAnnnotations注入框架使用之第三方框架集成Otto事件总线(十四)
- AndroidAnnnotations注入框架使用之第三方框架集成OrmLite(十五)
- AndroidAnnnotations注入框架使用之最佳实践之Adapters和lists(十六)
- AndroidAnnnotations注入框架使用之最佳实践SharedPreferences(十七)
- Android MVP开发模式详解(十九)
- 消息总线EventBus的基本使用(二十)
- 消息总线EventBus源码分析以及与Otto框架对比(二十一)
- 列表头生成带文本或者字母的图片开源库TextDrawable使用和详解(二十二)
- 重写WebView网页加载以及JavaScript注入详解(二十三)
- BaseAdapterHelper的基本使用介绍,让你摆脱狂写一堆Adapter烦恼(二十四)
- BaseAdapterHelper详解源码分析,让你摆脱狂写一堆Adapter烦恼(二十五)
- Volley完全解析之基础使用(二十六)
- Volley完全解析之进阶最佳实践与二次封装(二十七)
- RecyclerView完全解析,让你从此爱上它(二十八)
- RecyclerView完全解析之打造新版类Gallery效果(二十九)
- RecyclerView完全解析之结合AA(Android Annotations)注入框架实例(三十)
- RecyclerView完全解析之下拉刷新与上拉加载SwipeRefreshLayout(三十一)
- CardView完全解析与RecyclerView结合使用(三十二)
- 神器ViewDragHelper完全解析,妈妈再也不担心我自定义ViewGroup滑动View操作啦~(三十三)
- 神器ViewDragHelper完全解析之详解实现QQ5.X侧滑酷炫效果(三十四)
- 实例解析之SwipeRefreshLayout+RecyclerView+CardView(三十五)
- HorizontalScrollView,Fragment,FragmentStatePagerAdapter打造网易新闻Tab及滑动页面效果(三十六)
- Android Design支持库TabLayout打造仿网易新闻Tab标签效果(三十七)
- 打造QQ6.X最新版本侧滑界面效果(三十八)