Android中的MVP架构分解和实现

标签: geek | 发表时间:2017-02-07 00:00 | 作者:
出处:http://itindex.net/admin/pagedetail

1、概述

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

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

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

这里写图片描述

2、MVP介绍

这里写图片描述

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架构区别:

这里写图片描述

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

3、MVP实现

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

项目结构如下:
这里写图片描述

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

   packagecom.chunsoft.blogcontent.bean;/**
 * Developer:chunsoft on 2017/2/7 11:19
 * Email:chun_soft@qq.com
 * 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:chun_soft@qq.com
 * 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:chun_soft@qq.com
 * 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:chun_soft@qq.com
 * 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:chun_soft@qq.com
 * 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:chun_soft@qq.com
 * 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:chun_soft@qq.com
 * 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结合进行开发,逻辑更加清晰,下篇文章将详细介绍这部分实现。

相关 [android mvp 架构] 推荐:

Android中的MVP架构分解和实现

- - IT瘾-geek
传统的Android开发架构一般是MVC模式,. Model:业务逻辑和实体模型. View:对应于布局文件. Controllor:对应于Activity. 单独从逻辑看起来非常好,与我们做Web开发时,开发模式类似,但在实际开发中,View对应于布局文件,实际上关于该布局文件中的数据绑定的操作,事件处理的代码都在Activity中,Activity既像View又像Controller(MVVP架构中包括数据绑定),导致Activity中职责太重,耦合度大.

2011 品牌 MVP :Google

- wind - 谷奥——探寻谷歌的奥秘
BrandFinance® 公布了他们的年度报告,并将年度最有价值品牌奖颁给了 Google. 微软从去年的第五名升到了第二名,而去年冠军 Walmart 则落到了第三. Apple 则从第二十名火箭般窜升至第八. BrandFinance® 称:. 正因为这个世界越来越依赖互联网,所以才会将 Google 推向第一名的位置.

[Architecture] MVP, MVC, MVVM, 傻傻分不清楚~

- Amo - 點部落-小朱® 的技術隨手寫

Android 系统架构分析

- - CSDN博客移动开发推荐文章
Android:开源的 Linux + Google 的封闭软件 + 私有的基带 + 运营商锁定 = 开放的 Android 手机. iPhone:开源的 BSD + 苹果的闭源软件 + 私有的基带 + 运营商锁定 = 封闭的苹果 iPhone. 一个平庸的应用商店,开发者依靠广告赚钱,商店并非独此一家,用户找不到好软件.

Android 架构演化之路

- - 移动开发 - ITeye博客
关注微信号:javalearns   随时随地学Java. 在开始之前, 我这里假设大家都读过了我之前用简洁的办法架构Android程序一文. 如果你还没有读过, 现在应该去读一下那篇文章, 读过之后可以更好的理解我下面要讲的内容.. 演化是指一个事物变化成为另一个不同的事物的一个平缓过程, 通常情况下会变得更加复杂或者变成更好..

利用 MVP 與 Cells 整理你的程式碼

- chitsaou - Blog.XDite.net
在這次的 rubyconf 中,我在整理程式碼的技巧中,介紹了兩節比較少人使用的技巧:MVP 與 Cells. 沒錯,MVP 其實就是 Model – View – Presenter 的縮寫. 在一般實作 MVC 架構時,我們強調的是. 用於封裝與 「業務邏輯相關的資料」 以及 「對資料的處理方法」 必須放在 Model.

MVP(最小可行产品)的重要含义

- - 明学的白板
SILY系列文章第52期:MVP 必须向用户提供价值,换句话说,也就是验证问题是否真的存在,解决方案是否真的带来了改善. 精益创业中强调要使用 MVP 来验证问题确实存在,而 MVP 其实是最多被误解的一个定义. MVP 和 高保真原型的区别是什么. @jopas,画了一张非常棒的图表,让 MVP 的概念瞬间清晰:.

社区讨论:Android的架构设计

- - InfoQ cn
最近,开发者在知乎社区中就Android的架构设计展开了 讨论. 有人问“Android 架构设计的思想与原则是什么. 最近工作中遇到了Android中的权限问题,发现Android确实是开源的,但并不开放,比如权限控管就相当严格,限制做很多事情,这一点得益于Linux内核. 这也勾起来对其架构研究的兴趣,不知到哪位能够深度剖析下Android架构设计的思想与原则.

安居客Android项目架构演进

- - SegmentFault 最新的文章
入职安居客三年从工程师到Team Leader,见证了Android团队一路走来的发展历程. 因此有心将这些记录下来与大家分享,也算是对自己三年来一部分工作的总结. 希望对大家有所帮助,更希望能得到大家宝贵的建议. 三年前入职时安居客在业务上刚完成了三网合并(新房、二手房、好租和商业地产多个平台多个网站合成现在的anjuke.com,这在公司的历史上称之为三网合并),因此app端也将原先的新房、二手房、好租和商业地产多个app合并成为了现在的安居客app.

Android层次化安全架构及核心组件概览

- - 酷勤网-挖经验 [expanded by feedex.net]
Android系统承袭了Linux开源操作系统的安全特性,并采用了层次化的方式来保证系统安全,本文将详细介绍Android层次化安全架构及其核心组件. Android层次化安全架构. Android作为一个移动设备的平台,其软件层次结构包括了一个操作系统(OS),中间件(MiddleWare)和应用程序(Application).