Android架构篇--MVP模式的介绍篇
摘要: 在MVVM成熟之前MVP模式在Android上有被神化的趋势,笔者曾经在商业项目中从零开始大规模采用过MVP模式对项目进行开发。在使用MVP模式进行开发的时候发现项目的结构模式对开发是有一定的影响的,在这里笔者会对这一问题进行探讨。希望通过这篇blog能让读者了解如何使用MVP模式搭建一个功能完善的MVP模式开发框架,避免一些笔者认为比较严重的问题。
为什么要使用MVP模式
在传统的Android开发中,我们一般是使用MVC模式进行开发的。
传统MVC模式介绍:
- View: 视图层,对应xml文件
- Controller: 控制层,对应Activity和Fragment层,进行数据处理
- Model:实体层,负责获取实体数据
在Android开发中采用MVC模式的一个最大的弊端就是xml作为View层视图能力实在太弱,所以一般情况下我们都是通过Controller层来辅助处理一些视图的。这样的结果就导致Controller既作为控制层的同时又承担了View层的大部分功能,采用MVC模式往往会导致Activity和Fragment中的代码非常复杂。我们将Android中采用的MVC模式称为MV模式更加恰当。
MVP模式介绍:
- View: 视图层,对应xml文件与Activity/Fragment
- Presenter: 逻辑控制层,同时持有View和Model对象
- Model: 实体层,负责获取实体数据
MVP模式的流程图如下:
采用MVP模式的优势是:
- 把业务逻辑抽离到Presenter层中,View层专注于UI的处理。
- 分离视图逻辑与业务逻辑,达到解耦的目的。
- 提高代码的阅读性。
- Presenter被抽象成接口,可以根据Presenter的实现方式进行单元测试。
- 可拓展性强。
采用MVP模式的缺点:
- 项目结构会对后期的开发和维护有一定的影响。具体视APP的体量而定。
- 代码量会增多,如何避免编写过多功能相似的重复代码是使用MVP开发的一个重点要处理的问题。
- 有一定的学习成本。
综上所述,在Android上采用MVP模式的优势是:大大优化代码的维护性与拓展性的同时对代码进行深度解耦,使各个层级的分工更加明晰。
Android上MVP模式的简单应用
先来看看一个简单用mvp模式模拟登陆的demo,下面的示例代码和其它简单介绍MVP模式的代码没有太大区别。如果有了解过的同学可以直接跳过看下一章关于如何优化MVP模式的结构的文章。
下面我们来看看在Android上用MVP模式实现简单的登录逻辑的方式:
. 登陆界面
- 项目的结构:
项目结构
从上面的代码结构图可看出,用MVP模式实现登陆模块需要创建6个文件,分别是M、V、P接口文件和接口的对应实现。其中LoginActivity就是View层的具体实现。这样的好处时Activity组件只需要负责处理UI相关逻辑就可以了,而相关的业务逻辑全部抽象到Presenter层中处理。通过这种方式能够很好的避免传统Android开发中的Activity/Fragment等UI组件既负责处理UI逻辑又处理业务逻辑的结果。
. 代码实现
说了这么多,最后我们来看看代码的实现吧。
ILoginModel
123public interface ILoginModel {void login(String name ,String password);}ILoginPresenter
123456public interface ILoginPresenter {void loginToServer(String userName,String password);void loginSucceed();}ILoginView
123456public interface ILoginView {void showProgress(boolean enable);void showLoginView();}
上面是登陆模块对应的MVP接口的具体设计,下面我来简单介绍一下接口中的几个方法:
ILoginModel.login(String name ,String password)
登陆方法,通过该方法向服务器发送登陆请求。ILoginPresenter. loginToServer (String name ,String password)
通知Model响应登陆事件。ILoginPresenter. loginSucceed()
当登陆事件完成时(成功/失败),Model层要通知该方法登陆事件已完成。ILoginView. showProgress(boolean enable)
当Presenter层调用loginToServer (String name ,String password)
方法时,要通过该方法通知View层显示加载动画。ILoginView. showLoginView()
登陆成功时,Presenter层会通过该方法通知View层登陆已成功。
下面我们来看看这几个接口的具体实现。
- LoginModel
1234567891011121314151617181920212223public class LoginModel implements ILoginModel{private ILoginPresenter presenter;private Handler mHandler = new Handler();public LoginModel(ILoginPresenter presenter) {this.presenter = presenter;}@Overridepublic void login(String name ,String password) {mHandler.postDelayed(new Runnable() {@Overridepublic void run() {Log.d("LoginModel", "run: ");presenter.loginSucceed();}},2000);}}
上面的Model层实现了login(String name,Stringpassword)
登陆方法,该方法的具体实现逻辑是通过线程休眠2秒来模拟网络登陆的过程,登陆成功后会通过LoginPresenter的loginSucceed()
方法来通知Presenter层登陆结果。实际开发中我们需要根据具体的业务逻辑来实现该过程。
- LoginPresenter
1234567891011121314151617181920212223public class LoginPresenter implements ILoginPresenter{private ILoginModel loginModel;private ILoginView loginView;public LoginPresenter(ILoginView loginView) {this.loginView = loginView;this.loginModel = new LoginModel(this);}@Overridepublic void loginToServer(String userName, String password) {loginView.showProgress(true);loginModel.login(userName,password);}@Overridepublic void loginSucceed() {loginView.showProgress(false);loginView.showLoginView();}}
从上面代码可以看出LoginPresenter的实现逻辑很简单,首先在构造方法中获取ILoginView对象并撞见ILoginModel对象。然后当View层调用loginToServer(String userName, String password)
方法成功时,通知View层显示加载动画并调用ILoginModel层的login(String userName, String password)
方法向服务器发送登陆请求。当登陆成功后(即Model层通知loginSucceed方法时)通过loginView.showProgress(false)
方法通知View层隐藏加载动画,并通知View登陆成功。
- LoginActivity
对于LoginActivity我们只需要关注其中的几个方法即可1234567loginBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//模拟登陆,不需要账号密码loginPresenter.loginToServer("","");}});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Override
public void showProgress(boolean enable) {
if (enable){
progressBar.setVisibility(View.VISIBLE);
loginLayout.setVisibility(View.GONE);
}else {
progressBar.setVisibility(View.GONE);
loginLayout.setVisibility(View.VISIBLE);
}
}
@Override
public void showLoginView() {
Toast.makeText(LoginActivity.this,"登陆功",Toast.LENGTHSHORT).show();
finish();
}
|
上面时实现了ILoginView接口的两个方法。
结合上面的代码可以看出,当点击登陆按钮的监听事件时,我们不需要关注业务逻辑,只需要调用loginPresenter.loginToServer("","");
方法即可,然后根据实际情况实现View层中ILoginView接口的方法即可,这样达到了UI业务与逻辑完全分离的目的。
Android架构篇--MVP模式的介绍篇的更多相关文章
- [译]Google官方关于Android架构中MVP模式的示例
概述 该示例(TODO-MVP)是后续各种示例演变的基础,它主要演示了在不带架构性框架的情况下实现M-V-P模式.其采用手动依赖注入的方式来提供本地数据源和远程数据源仓库.异步任务通过回调处理. 注意 ...
- Google官方关于Android架构中MVP模式的示例续-DataBinding
基于前面的TODO示例,使用Data Binding库来显示数据并绑定UI元素的响应动作. 这个示例并未严格遵循 Model-View-ViewModel 或 Model-View-Presenter ...
- 如何结合整洁架构和MVP模式提升前端开发体验 - 整体架构篇
本文不详细介绍什么是整洁架构以及 MVP 模式,自行查看文章结尾相关链接文章. 整洁架构粗略介绍 下图为整洁架构最原始的结构图: Entities/Models:实体层,官方说法就是封装了企业里最通用 ...
- Android MVP模式简单易懂的介绍方式 (二)
Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 上一篇文章我们介绍完了Model的创建 ...
- DDD分层架构之值对象(介绍篇)
DDD分层架构之值对象(介绍篇) 前面介绍了DDD分层架构的实体,并完成了实体层超类型的开发,同时提供了验证方面的支持.本篇将介绍另一个重要的构造块——值对象,它是聚合中的主要成分. 如果说你已经在使 ...
- Android MVP模式 简单易懂的介绍方式
主要学习这位大神的博客:简而易懂 Android MVP模式 简单易懂的介绍方式 https://segmentfault.com/a/1190000003927200
- Android MVP模式简单易懂的介绍方式 (三)
Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 讲完M和P,接下来就要讲V了.View ...
- Android MVP模式简单易懂的介绍方式 (一)
Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 最近正在研究Android的MVP模式 ...
- 浅谈Android架构之MVP,MVVM
概述 MVP(Model-View-Presenter)是传统MVC(Model-View-Controller)在Android开发上的一种变种.进化模式.主要用来隔离UI.UI逻辑和业务逻辑.数据 ...
随机推荐
- 报警系统:php输出头信息以方便脚本抓取信息[排查篇]
做监控系统时,需要对某个页面进行监控,可以通过很多方式进行报警,如:正常则输出一个规定的变量,错误时则不输出.但是还有一个更为方便的做法,就是当前错误时,直接使用header抛出信息,如: heade ...
- Vue-Cli 搭建项目 小白
vue-用Vue-cli从零开始搭建一个Vue项目 Vue是近两年来比较火的一个前端框架(渐进式框架吧). Vue两大核心思想:组件化和数据驱动.组件化就是将一个整体合理拆分为一个一个小块(组件),组 ...
- ASP.NET Web API实现微信公众平台开发(一)服务器验证
最近朋友的微信公众号准备做活动,靠固定的微信公众平台模版搞定不了,于是请我代为开发微信后台.鉴于我也是第一次尝试开发微信后台,所以也踩了不少坑,此系列博客将会描述微信公众号各项功能的实现. 先决条件 ...
- Python——破解极验滑动验证码
极验滑动验证码 以上图片是最典型的要属于极验滑动认证了,极验官网:http://www.geetest.com/. 现在极验验证码已经更新到了 3.0 版本,截至 2017 年 7 月全球已有十六万家 ...
- Comparable接口和Comparator接口的不同用法
两者都可用来在定义比较方法,然后用在排序中. Comparable是类本身继承的接口 Comparator实在类外定义一个排序的类 比较而言,觉得Comparator更灵活一些,但是Comparabl ...
- 什么是js的严格模式
设立严格模式的原因: - 消除Javascript语法的一些不合理.不严谨之处,减少一些怪异行为; - 消除代码运行的一些不安全之处,保证代码运行的安全: - 提高编译器效率,增加运行速度: - 为未 ...
- Python:SQLMap源码精读—start函数
源代码 def start(): """ This function calls a function that performs checks on both URL ...
- 小程序flex容器
flex:默认:水平方向是主轴,垂直方向是交叉轴,分布在第四象限,项目时在主轴方向上排列, 排满之后在交叉轴方向上换行: 1.设置容器的属性 display:flex 通过设置坐标轴来设置项目的排列方 ...
- 从零开始学 Web 之 CSS3(三)渐变,background属性
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- bigdata-01-应用
1, 基本概念 在互联网技术发展到现今阶段,大量日常.工作等事务产生的数据都已经信息化,人类产生的数据量相比以前有了爆炸式的增长,以前的传统的数据处理技术已经无法胜任,需求催生技术,一套用来处理海量数 ...