Android架构蓝图------MVP

来源:互联网 发布:道路工程预算软件 编辑:程序博客网 时间:2024/04/28 18:24

简介


2016年3月,为了管理我们的代码,Google Android Framework层开发工程师JoseAlcerreca提议了推出一款可以规范我们的代码,一种新型的架构思想,官方命名为”Android Architecture Blueprints”,我们编码看起更加的自由灵活,实现了完全解耦,同时也导致产生大量的class文件,今天小木箱就带大家深入浅出的进入Android架构蓝图——MVP


现在Android应用主流架构是:Retrofit+OkHttp+RxJava+MVP,MVP全称Modle+View+Present,其中Present解耦了Modle和View,使模块的职责变得更加单一,Modle,顾名思义,模型,负责管理data,我们把它叫做数据层,view只管理视图的绘制也就是我们的UI层


MVC 释意 作用 M Modle 业务逻辑和实体模型–如:网络数据库 V view 对应xml布局文件-Layout C Controllor Activity

这是我们传统的MVC设计模式

这里写图片描述

MVP相对与传统的MVC而言更加易于维护和Junit测试,因为他实现了完全的解耦

MVP 释意 作用 M Modle 数据层,业务逻辑和实体模型 V view view绘制以及用户交互,对应的Activity界面 P Present 负责UI和Modle之间的接耦

这里写图片描述

当然MVP也有缺点,比如一个Project的class文件增加了,每一层都需要接口和实现类,在System相对不是很稳定的时候,我们可以直接舍弃Present和Modle层,MVP没有固定的模板,每一层都可以根据各自的业务场景做相应的调整,并不是所有的页面都可以采用MVP模式,其他简单的界面完全可以用原来自己的实现方式,下面我就写一个简单的MVP-LoginSample

这里写图片描述

需求是这样的:

  • 界面展示
  • 用户输入
  • 按钮点击
  • 判断用户输入
  • 显示滚动条
  • 一系列耗时操作
  • 隐藏进度条
  • 提示用户

这里写图片描述

(一)Modle数据层

public class User {   public String username;   public String password;}

上面我说过了,Present和view之间的交互是通过接口,所以我们在这里面定义一个IUserLoginView 这样一个接口,我们一眼就可以看到,效果图里面有一个登录的Button,login说明了存在登陆成功或者失败的处理,成功可能跳转首页,失败给个提醒,所以我在这里面写了两个接口方法,有了接口实现就太好写了,我们要考虑一下:该操作的结果对应的用户反馈(success,Failer):

public interface IUserLoginView {   void success();// 登陆成功   void Failer();//登录失败}

从效果图可以看出这里至少有一个login()的方法

public class UserLoginNet {   /**    * 发送用户输入数据    * @param user    * @return    */   public  boolean sendUseLoginInfo(User user){      SystemClock.sleep(2000);      if ("18390833563".equals(user.username) && "123456".equals(user.password)) {         return  true;      } else {         return  false;       }   }}

(二View)

下面是我的view的实现类,其实就是Activity,对MVP里面的P就是我们的Activity或者Fragment**

/** * 视图层,view绘制以及用户交互,对应的Activity界面 */public class LoginActivity extends Activity implements View.OnClickListener, IUserLoginView {   private EditText phone;   private EditText password;   private Button btn_login;   private ProgressDialog dialog;   private User user;   private UserLoginPresent userloginpresent;   private String username;   private String mpassword;   @Override   protected void onCreate(Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      setContentView(R.layout.activity_login);      user = new User();      phone = (EditText) findViewById(R.id.et_email_phone);      password = (EditText) findViewById(R.id.password);      btn_login = (Button) findViewById(R.id.btn_login);      phone.setOnClickListener(this);      password.setOnClickListener(this);      btn_login.setOnClickListener(this);      dialog = new ProgressDialog(this);      userloginpresent = new UserLoginPresent(this);   }   @Override   public void onClick(View v) {      username = phone.getText().toString();      mpassword = password.getText().toString();      user.username = username;      user.password = mpassword;      boolean checkUserInfo = userloginpresent.checkUserInfo(user);      switch (v.getId()){         case  R.id.btn_login:            if (checkUserInfo) {               dialog.show();               userloginpresent.login(user);            } else {               Toast.makeText(this, "用户名密码不能为空", Toast.LENGTH_LONG).show();            }            break;      }}   public void success() {      runOnUiThread(new Runnable() {         @Override         public void run() {            dialog.dismiss();            Toast.makeText(LoginActivity.this, "欢迎回来" + user.username, Toast.LENGTH_LONG).show();         }      });   }   public void Failer() {      runOnUiThread(new Runnable() {         @Override         public void run() {            dialog.dismiss();            Toast.makeText(LoginActivity.this, "用户名或密码有误" + user.username, Toast.LENGTH_LONG).show();         }      });   }}

在Activty中实现我们上述定义的接口,是一件非常容易的事情,因为是接口引导我们去做事情,当然Present是中间的桥梁,那么Present是怎样实现Modle与View之间的解耦了,请看下面的代码

(三)present

/** * 业务层用于UI和Activity之间的解耦 */public class UserLoginPresent {   //Activity 和 Frament 的通用性不好   //开发中一般用接口代替   private IUserLoginView view;   public UserLoginPresent(IUserLoginView activity) {      this.view = activity;   }   public boolean checkUserInfo(User user) {      if (TextUtils.isEmpty(user.username) || TextUtils.isEmpty(user.password)) {         return false;      }      return true;   }   public void login(final User user) {      UserLoginNet userLoginNet = new UserLoginNet();      new Thread() {         @Override         public void run() {            UserLoginNet userLoginNet = new UserLoginNet();            if (userLoginNet.sendUseLoginInfo(user)) {               view.success();            } else {               view.Failer();            }         }      }.start();   }}

Activity只要关心如何绘制UI,把逻辑处理的工作丢给了Presenter,同时存取数据的活交给了Model,Presenter 通过 Model 获取数据,通知 View 绘制界面。而且他们之间又是通过接口耦合的,只要替换掉实现,就能方便的改变需求,Presenter实现中可以不包含任何Android相关的代码,因为是纯Java代码,所以可以方便的使用JUnit配合Mokito进行单元测试。

以上纯属个人见解,欢迎吐槽,如有不妥之处,请老司机多多指教。~~~

这里写图片描述

0 0
原创粉丝点击