Android中的MVP架构分解和实现

1、概述

传统的Android开发架构一般是MVC模式,

  • Model:业务逻辑和实体模型
  • View:对应于布局文件
  • Controllor:对应于Activity

单独从逻辑看起来非常好,与我们做Web开发时,开发模式类似,但在实际开发中,View对应于布局文件,实际上关于该布局文件中的数据绑定的操作,事件处理的代码都在Activity中,Activity既像View又像Controller(MVVP架构中包括数据绑定),导致Activity中职责太重,耦合度大。修改和维护起来非常麻烦。

Android中的MVP架构分解和实现_第1张图片

2、MVP介绍

Android中的MVP架构分解和实现_第2张图片

MVP架构中,View 对应于Activity,负责View的绘制以及与用户交互
Model 依然是业务逻辑和实体模型,Presenter 负责完成View于Model间的交互。

(1)Model层

模型层之中做的工作是具体业务逻辑处理的实现,都伴随着程序中各种数据的处理,复杂一些的就需要实现一个Interface来松耦合了。

(2)View层

视图层体现的很轻薄,负责显示数据、提供友好界面跟用户交互就行。MVP下Activity和Fragment体现在了这一 层,Activity一般也就做加载UI视图、设置监听再交由Presenter处理的一些工作,所以也就需要持有相应Presenter的引用。处理一些基本UI逻辑,判断是否为空。

(3)Presenter层

Presenter这一层处理着程序各种逻辑的分发,收到View层UI上的反馈命令、定时命令、系统命令等指令后分发处理逻辑交由Model层做具体的业务操作。

MVP架构和MVC架构区别:

Android中的MVP架构分解和实现_第3张图片

MVC中是允许Model和View进行交互的,而MVP中,Model与View之间的交互由Presenter完成。还有一点就是Presenter与View之间的交互是通过接口的。

3、MVP实现

百说不如一做。实现一个简单的登录操作。

项目结构如下:
Android中的MVP架构分解和实现_第4张图片

(1)Model层实现
首先实现User实体类:

   packagecom.chunsoft.blogcontent.bean;/**
 * Developer:chunsoft on 2017/2/7 11:19
 * Email:[email protected]
 * Content:实体类
 */publicclassUser{privateString username;privateString password;publicStringgetUsername() {returnusername;
    }publicvoidsetUsername(String username) {this.username = username;
    }publicStringgetPassword() {returnpassword;
    }publicvoidsetPassword(String password) {this.password = password;
    }
}

model层主要实现业务逻辑处理,在本文案例中,主要逻辑处理就是登录,抽取了一个接口和一个实现类,在login操作,模拟登录操作,Thread.sleep()模拟耗时,由于是耗时操作,通过一个回调接口通知登录状态。

model层接口:

   packagecom.chunsoft.blogcontent.model;importcom.chunsoft.blogcontent.RequestCallback;importcom.chunsoft.blogcontent.bean.User;/**
 * Developer:chunsoft on 2017/2/7 11:30
 * Email:[email protected]
 * Content:Model层主要处理业务方法和实体模型
 */publicinterfaceLoginModel{voidlogin(String username, String password, RequestCallback<User> callback);
}

model层接口实现:

   packagecom.chunsoft.blogcontent.model.impl;importcom.chunsoft.blogcontent.RequestCallback;importcom.chunsoft.blogcontent.bean.User;importcom.chunsoft.blogcontent.model.LoginModel;/**
 * Developer:chunsoft on 2017/2/7 11:31
 * Email:[email protected]
 * Content:Model层的实现
 */publicclassLoginModelImplimplementsLoginModel{@Overridepublicvoidlogin(finalString username,finalString password,finalRequestCallback<User> callback) {//模仿登录操作newThread() {@Overridepublicvoidrun() {try{
                    Thread.sleep(2*1000);
                }catch(InterruptedException e) {
                    e.printStackTrace();
                }if("chunsoft".equals(username) &&"123456".equals(password)) {
                    User user =newUser();
                    user.setUsername(username);
                    user.setPassword(password);
                    callback.onSuccess(user);
                }else{
                    callback.onFailure("登录失败");
                }
            }
        }.start();
    }
}

回调接口:

   packagecom.chunsoft.blogcontent;/**
 * Developer:chunsoft on 2017/2/7 11:35
 * Email:[email protected]
 * Content:回调接口
 */publicinterfaceRequestCallback<T> {voidonSuccess(T datas);voidonFailure(String msg);
}

(2)View层实现

对于View层接口定义,首先考虑功能上的操作,然后考虑:

  • 该操作需要什么?(getUserName等)
  • 该操作的结果,对应的反馈?(toMainActivity等)
  • 该操作过程中交互友好?( showLoading)

view层接口:

   packagecom.chunsoft.blogcontent.view;importcom.chunsoft.blogcontent.bean.User;/**
 * Developer:chunsoft on 2017/2/7 11:54
 * Email:[email protected]
 * Content:view层接口
 */publicinterfaceLoginView{String getUserName();
    String getPassword();voidshowLoading();voidhideLoading();voidtoMainActvity(User user);voidshowFailedError(String msg);
}

view层实现,其实就是Activity,可以看到Activity的代码量大大减少,且逻辑清晰:

   packagecom.chunsoft.blogcontent;importandroid.os.Bundle;importandroid.support.v7.app.AppCompatActivity;importandroid.view.View;importandroid.widget.Button;importandroid.widget.EditText;importandroid.widget.ProgressBar;importandroid.widget.Toast;importcom.chunsoft.blogcontent.bean.User;importcom.chunsoft.blogcontent.presenter.impl.LoginPresenterImpl;importcom.chunsoft.blogcontent.view.LoginView;publicclassMainActivityextendsAppCompatActivityimplementsLoginView{privateEditText et_mobile,et_password;privateProgressBar pb;privateButton btn_login;privateLoginPresenterImpl mLoginPresenter =newLoginPresenterImpl(this);@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        et_mobile = (EditText) findViewById(R.id.et_mobile);
        et_password = (EditText) findViewById(R.id.et_password);
        pb = (ProgressBar) findViewById(R.id.pb);
        btn_login = (Button) findViewById(R.id.btn_login);

        btn_login.setOnClickListener(newView.OnClickListener() {@OverridepublicvoidonClick(View v) {
                mLoginPresenter.login();
            }
        });
    }@OverridepublicStringgetUserName() {returnet_mobile.getText().toString();
    }@OverridepublicStringgetPassword() {returnet_password.getText().toString();
    }@OverridepublicvoidshowLoading() {
        pb.setVisibility(View.VISIBLE);
    }@OverridepublicvoidhideLoading() {
        pb.setVisibility(View.INVISIBLE);
    }@OverridepublicvoidtoMainActvity(User user) {
        Toast.makeText(this,user.getUsername() +"登录成功",Toast.LENGTH_SHORT).show();
    }@OverridepublicvoidshowFailedError(String msg) {
        Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
    }
}

(3)Presenter层实现

Presenter层是Model层和View层的桥梁,本文中依然抽象出一个接口和一个实现类,定义时主要看该功能有什么操作,例如,登录:

Presenter接口:

   packagecom.chunsoft.blogcontent.presenter;/**
 * Developer:chunsoft on 2017/2/7 11:49
 * Email:[email protected]
 * Content:Presenter层接口
 */publicinterfaceLoginPresenter{voidlogin();
}

Presenter层实现:

   packagecom.chunsoft.blogcontent.presenter.impl;importandroid.os.Handler;importcom.chunsoft.blogcontent.RequestCallback;importcom.chunsoft.blogcontent.bean.User;importcom.chunsoft.blogcontent.model.LoginModel;importcom.chunsoft.blogcontent.model.impl.LoginModelImpl;importcom.chunsoft.blogcontent.presenter.LoginPresenter;importcom.chunsoft.blogcontent.view.LoginView;/**
 * Developer:chunsoft on 2017/2/7 11:50
 * Email:[email protected]
 * Content:Presenter层实现
 */publicclassLoginPresenterImplimplementsLoginPresenter{privateLoginView loginView;privateLoginModel loginModel;privateHandler mHandler =newHandler();//在构造函数中初始化publicLoginPresenterImpl(LoginView loginView) {this.loginModel =newLoginModelImpl();this.loginView = loginView;
    }@Overridepublicvoidlogin() {
        loginView.showLoading();
        loginModel.login(loginView.getUserName(), loginView.getPassword(),newRequestCallback<User>() {@OverridepublicvoidonSuccess(finalUser datas) {//登录成功mHandler.post(newRunnable() {@Overridepublicvoidrun() {
                        loginView.toMainActvity(datas);
                        loginView.hideLoading();
                    }
                });
            }@OverridepublicvoidonFailure(finalString msg) {//登录失败mHandler.post(newRunnable() {@Overridepublicvoidrun() {
                        loginView.showFailedError(msg);
                        loginView.hideLoading();
                    }
                });
            }
        });
    }
}

Presenter层是Model层和View层的桥梁,Model层和View层不直接通信,所以Presenter层需要Model层和View层的实现类,从View层中获取重要参数,交给Model 层调用业务逻辑处理,执行后的结果和反馈再交给View层去展示。

本文源码下载

本文是简单的用MVP架构实现登录操作,而目前主流开发,将Rxjava、Retrofit和MVP结合进行开发,逻辑更加清晰,下篇文章将详细介绍这部分实现。

你可能感兴趣的:(Geek)