【FastDev4Android框架开发】Android MVP开发模式详解(十九)

jerry Android 2015年11月26日 收藏

().前言:   

      今天我们的项目继续更新,今天我们主要讲解MVP开发模式以及具体实例。

     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

   对应的交互图如下:

  

   虽然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层的交互操作。

 数据交互图如下:

观察上面两个模式的交互图,是不是MVP模式更加清晰简单啊!

().MVCMVP区别:   

     我们来具体看一下下面两张对比,就可以看来具体区别了:

观察上图我们可以发现MVP模式中,ViewModel的交互是通过Presenter来进行完成,这样统一管理,逻辑会更加清晰。

().MVP模式例子讲解:   

      4.1.具体实现功能需求:我们是用MVP模式来进行实现用户登录操作.

      4.2.例子实例如下

           

    4.3.项目代码框架如下:


     


     

    4.4.代码具体实现:

        4.4.1.Model:Bean(Entity)PersonBean类,然后在业务逻辑类中有登录方法,同时把登录成功状态回调接口传入进入,具体如下:


  1. packagecom.chinaztt.fda.entity;
  2.  
  3. /**
  4.  * 当前类注释:用户信息实体类
  5.  * 项目名:FastDev4Android
  6.  * 包名:com.chinaztt.fda.entity
  7.  * 作者:江清清 on 15/10/27 14:13
  8.  * 邮箱:jiangqqlmj@163.com
  9.  * QQ: 781931404
  10.  * 公司:江苏中天科技软件技术有限公司
  11.  */
  12. public class PersonBean {
  13.     private String username;
  14.     private String password;
  15.  
  16.     public PersonBean() {
  17.     }
  18.  
  19.     public PersonBean(String username, Stringpassword) {
  20.         this.username = username;
  21.         this.password = password;
  22.     }
  23.  
  24.     public String getUsername() {
  25.         return username;
  26.     }
  27.  
  28.     public void setUsername(String username) {
  29.         this.username = username;
  30.     }
  31.  
  32.     public String getPassword() {
  33.         return password;
  34.     }
  35.  
  36.     public void setPassword(String password) {
  37.         this.password = password;
  38.     }
  39.  
  40.     @Override
  41.     public String toString() {
  42.         return "PersonBean{" +
  43.                 "username='" +username + '\'' +
  44.                 ", password='" +password + '\'' +
  45.                 '}';
  46.     }
  47. }
  1. public interface IPersonBiz {
  2.     void login(String username,Stringpassword,LoginRequestCallBack valueCallBack);
  3. }

  1. packagecom.chinaztt.fda.biz.imp;
  2.  
  3. importcom.chinaztt.fda.biz.IPersonBiz;
  4. importcom.chinaztt.fda.biz.LoginRequestCallBack;
  5. importcom.chinaztt.fda.entity.PersonBean;
  6. importcom.chinaztt.fda.utils.Log;
  7.  
  8. /**
  9.  * 当前类注释:用户相关业务逻辑实现类
  10.  * 项目名:FastDev4Android
  11.  * 包名:com.chinaztt.fda.biz.imp
  12.  * 作者:江清清 on 15/10/27 16:33
  13.  * 邮箱:jiangqqlmj@163.com
  14.  * QQ: 781931404
  15.  * 公司:江苏中天科技软件技术有限公司
  16.  */
  17. public class PersonBizImp implements IPersonBiz{
  18.     private static final  String TAG="PersonBizImp";
  19.     @Override
  20.     public void login(final String username,final String password, final LoginRequestCallBack valueCallBack) {
  21.        Log.d(TAG,"username:"+username+",password:"+password);
  22.         new Thread(new Runnable() {
  23.             @Override
  24.             public void run() {
  25.                 try {
  26.                     Thread.sleep(4500);
  27.                 } catch (InterruptedExceptione) {
  28.                     e.printStackTrace();
  29.                 }
  30.                 //进行开始登录,这边应该进行请求服务器,进行数据验证
  31.                if(username.equals("jiangqq")&&password.equals("12345")){
  32.                    valueCallBack.loginSuccess(new PersonBean(username,password));
  33.                 }else{
  34.                    valueCallBack.loginFailed();
  35.                 }
  36.             }
  37.         }).start();
  38.     }
  39. }
  1. packagecom.chinaztt.fda.biz;
  2.  
  3. importcom.chinaztt.fda.entity.PersonBean;
  4. /**
  5.  * 当前类注释:登录请求结果回调
  6.  * 项目名:FastDev4Android
  7.  * 包名:com.chinaztt.fda.biz
  8.  * 作者:江清清 on 15/10/27 19:50
  9.  * 邮箱:jiangqqlmj@163.com
  10.  * QQ: 781931404
  11.  * 公司:江苏中天科技软件技术有限公司
  12.  */
  13. public interface LoginRequestCallBack {
  14.     //登录成功回调方法
  15.     void loginSuccess(PersonBean personBean);
  16.     //登录失败回调方法
  17.     void loginFailed();
  18. }


4.4.2.View:该通过PresenterView进行交互,这边需要定义一个接口ILoginView


  1. packagecom.chinaztt.fda.ui.view;
  2.  
  3. importcom.chinaztt.fda.entity.PersonBean;
  4.  
  5. /**
  6.  * 当前类注释:登录页面 相关操作 功能接口
  7.  * 项目名:FastDev4Android
  8.  * 包名:com.chinaztt.fda.ui.view
  9.  * 作者:江清清 on 15/10/27 16:35
  10.  * 邮箱:jiangqqlmj@163.com
  11.  * QQ: 781931404
  12.  * 公司:江苏中天科技软件技术有限公司
  13.  */
  14. public interface ILoginView {
  15.     //获取用户名
  16.     String getUserName();
  17.     //获取密码
  18.     String getPassword();
  19.   
  20.     void showSuccessInfo(PersonBeanpersonBean);
  21.     void showFailedInfo();
  22. }


 有了上面的接口之后,我们就需要写我们的实现类Activity了,就非常简单了


  1. packagecom.chinaztt.fda.test;
  2.  
  3. importandroid.os.Bundle;
  4. importandroid.view.View;
  5. importandroid.widget.Button;
  6. importandroid.widget.EditText;
  7.  
  8. importcom.chinaztt.fda.entity.PersonBean;
  9. importcom.chinaztt.fda.presenter.LoginPresenter;
  10. importcom.chinaztt.fda.ui.R;
  11. importcom.chinaztt.fda.ui.base.BaseActivity;
  12. importcom.chinaztt.fda.ui.view.ILoginView;
  13. importcom.chinaztt.fda.utils.Log;
  14.  
  15. importorg.androidannotations.annotations.EActivity;
  16.  
  17. /**
  18.  * 当前类注释:MVP开发模式实例
  19.  * 项目名:FastDev4Android
  20.  * 包名:com.chinaztt.fda.test
  21.  * 作者:江清清 on 15/10/27 13:38
  22.  * 邮箱:jiangqqlmj@163.com
  23.  * QQ: 781931404
  24.  * 公司:江苏中天科技软件技术有限公司
  25.  */
  26. @EActivity
  27. public class MVPTestActivity extends BaseActivity implements ILoginView{
  28.     private static  final String TAG="MVPTestActivity";
  29.  
  30.     private EditText ed_username;
  31.     private EditText ed_password;
  32.     private Button btn_login;
  33.     private LoginPresenter mLoginPresenter;
  34.     @Override
  35.     protected void onCreate(BundlesavedInstanceState) {
  36.         super.onCreate(savedInstanceState);
  37.        setContentView(R.layout.mvp_test_layout);
  38.        ed_username=(EditText)this.findViewById(R.id.ed_username);
  39.        ed_password=(EditText)this.findViewById(R.id.ed_password);
  40.        btn_login=(Button)this.findViewById(R.id.btn_login);
  41.         mLoginPresenter=newLoginPresenter(this);
  42.         btn_login.setOnClickListener(newView.OnClickListener() {
  43.             @Override
  44.             public void onClick(View v) {
  45.                 mLoginPresenter.loginSystem();
  46.  
  47.             }
  48.         });
  49.     }
  50.     /**
  51.      * 进行返回用户名信息
  52.      * @return
  53.      */
  54.     @Override
  55.     public String getUserName() {
  56.         returned_username.getText().toString().trim();
  57.     }
  58.     /**
  59.      * 进行返回用户密码信息
  60.      * @return
  61.      */
  62.     @Override
  63.     public String getPassword() {
  64.         returned_password.getText().toString().trim();
  65.     }
  66.     /**
  67.      * 登录成功 回调
  68.      * @param personBean
  69.      */
  70.     @Override
  71.     public void showSuccessInfo(PersonBeanpersonBean) {
  72.        Log.d(TAG,"showSuccessInfo:"+personBean.toString());
  73.        showToastMsgShort("登录成功:"+personBean.toString());
  74.     }
  75.     /**
  76.      * 登录失败 回调
  77.      */
  78.     @Override
  79.     public void showFailedInfo() {
  80.        Log.d(TAG,"showFailedInfo...");
  81.        showToastMsgShort("登录失败...");
  82.     }
  83. }


          最后还少一个交互桥梁Presenter:

 4.4.3.Presenter:作为ModelView之间的交互桥梁,在本例中进行执行登录操作,然后去Model业务中执行登录,最后把登录结果信息返回给View层,就是这么简单:


  1. packagecom.chinaztt.fda.presenter;
  2.  
  3. importandroid.os.Handler;
  4.  
  5. importcom.chinaztt.fda.biz.IPersonBiz;
  6. importcom.chinaztt.fda.biz.LoginRequestCallBack;
  7. importcom.chinaztt.fda.biz.imp.PersonBizImp;
  8. importcom.chinaztt.fda.entity.PersonBean;
  9. importcom.chinaztt.fda.ui.view.ILoginView;
  10. importcom.chinaztt.fda.utils.Log;
  11.  
  12. /**
  13.  * 当前类注释:负责完成登录界面View于Model(IPersonBiz)间的交互
  14.  * 项目名:FastDev4Android
  15.  * 包名:com.chinaztt.fda.presenter
  16.  * 作者:江清清 on 15/10/27 16:36
  17.  * 邮箱:jiangqqlmj@163.com
  18.  * QQ: 781931404
  19.  * 公司:江苏中天科技软件技术有限公司
  20.  */
  21. public class LoginPresenter {
  22.     private static final  String TAG="LoginPresenter";
  23.     private ILoginView mLoginView;
  24.     private IPersonBiz mPersonBiz;
  25.  
  26.     private Handler mHandler=new Handler();
  27.  
  28.     public LoginPresenter(ILoginView view) {
  29.         mLoginView = view;
  30.         mPersonBiz = new PersonBizImp();
  31.     }
  32.  
  33.     public void loginSystem(){
  34.       mPersonBiz.login(mLoginView.getUserName(), mLoginView.getPassword(), newLoginRequestCallBack() {
  35.            /**
  36.             * 登录成功
  37.             * @param personBean
  38.             */
  39.            @Override
  40.            public void loginSuccess(finalPersonBean personBean) {
  41.                Log.d(TAG,"登录成功:" + personBean.toString());
  42.                mHandler.post(new Runnable() {
  43.                    @Override
  44.                    public void run() {
  45.                       mLoginView.showSuccessInfo(personBean);
  46.                    }
  47.                });
  48.            }
  49.            /**
  50.             * 登录失败
  51.             */
  52.            @Override
  53.            public void loginFailed() {
  54.               Log.d(TAG,"登录失败...");
  55.                mHandler.post(new Runnable() {
  56.                    @Override
  57.                    public void run() {
  58.                       mLoginView.showFailedInfo();;
  59.                    }
  60.                });
  61.            }
  62.        });
  63.     }
  64. }


         到此我们的MVP模式的例子就大体完成了,看一下上面的效果演示就OK了。

我们的项目已经配置集成了MVPDemo的例子.欢迎大家去Github站点进行clone或者下载浏览:https://github.com/jiangqqlmj/FastDev4Android 同时欢迎大家starfork整个开源快速开发框架项目~