## (一).前言: 今天我们的项目继续更新,今天我们主要讲解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整个开源快速开发框架项目~