一、 什么是MVP

MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。

二、MVP与MVC的区别

作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。

MVC模式

MVP模式

三、Android中的MVP

代码案例:Login MVP

Model

/** 模型层 ——— 登录接口 **/

public interface ILoginModel {

void login(String username, String password, LoginCallBack callBack);

}

/** 模型层 ——— 完成具体的数据操作。 **/

public class LoginModel implements ILoginModel {

@Override

public void login(String username, String password, LoginCallBack callBack) {

if (username.equals("MVP") && password.equals("MVP")){

callBack.onLoginSuccess();

}else{

callBack.onLoginFail();

}

}

}

View

/** 视图层 ——— 视图操作接口 **/

public interface ILoginView {

void initView();

void onUsernameEmpty(); // 用户名为空时的显示操作

void onPasswordEmpty(); // 密码为空时的显示操作

void onLoginSuccess(); // 登陆成功时的显示操作

void onLoginFail(); // 密码失败时的显示操作

}

/** 视图层 ——— 只是作为接受用户数据和展示数据的方式 **/

public class LoginView extends LinearLayout implements ILoginView, View.OnClickListener{

private Context context;

private EditText mUsername;

private EditText mPassword;

private Button mLoginBtn;

private ILoginPresenter presenter;

public LoginView(Context context, AttributeSet attrs) {

super(context, attrs);

this.context = context;

}

@Override

public void initView(){

mUsername = (EditText) findViewById(R.id.et_username);

mPassword = (EditText) findViewById(R.id.et_password);

mLoginBtn = (Button) findViewById(R.id.btn_login);

presenter = new LoginPresenter(this);

}

@Override

public void onClick(View v) {

switch (v.getId()){

case R.id.btn_login:

presenter.login(mUsername.getText().toString(),

mPassword.getText().toString());

break;

}

}

@Override

public void onUsernameEmpty() {

Toast.makeText(context, "用户名不能为空", Toast.LENGTH_SHORT).show();

}

@Override

public void onPasswordEmpty() {

Toast.makeText(context, "密码不能为空", Toast.LENGTH_SHORT).show();

}

@Override

public void onLoginSuccess() {

Toast.makeText(context, "登录成功", Toast.LENGTH_SHORT).show();

}

@Override

public void onLoginFail() {

Toast.makeText(context, "登录失败", Toast.LENGTH_SHORT).show();

}

}

Presenter

public interface ILoginPresenter {

void login(String username, String password);

}

public class LoginPresenter implements ILoginPresenter, LoginCallBack{

private ILoginModel loginModel;

private ILoginView loginView;

public LoginPresenter(ILoginView loginView){

loginModel = new LoginModel();

this.loginView = loginView;

}

@Override

public void login(String username, String password) {

if (TextUtils.isEmpty(username)){

loginView.onUsernameEmpty();

}else if (TextUtils.isEmpty(password)){

loginView.onPasswordEmpty();

}else {

loginModel.login(username, password, this);

}

}

@Override

public void onLoginSuccess() {

loginView.onLoginSuccess();

}

@Override

public void onLoginFail() {

loginView.onLoginFail();

}

}

else

/** 此时Activity就变为了承载视图层的容器。 **/

public class MainActivity extends AppCompatActivity {

private LoginView loginview;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initPresenter();

}

private void initPresenter(){

loginview = (LoginView) findViewById(R.id.loginview);

loginview.initView();

}

}

xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

android:orientation="vertical"

android:id="@+id/loginview">

android:id="@+id/et_username"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:inputType="text"/>

android:id="@+id/et_password"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:inputType="textPassword"/>

android:id="@+id/btn_login"

android:layout_width="match_parent"

android:layout_height="50dp"

android:text="Login"

android:layout_marginTop="10dp"/>

三、 MVP模式的优缺点

优点:

1、模型与视图完全分离,我们可以修改视图而不影响模型

2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部

3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。

4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)

缺点:

由于对视图的渲染放在了Presenter中,所以视图和Presenter的交互会过于频繁。还有一点需要明白,如果Presenter过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密。一旦视图需要变更,那么Presenter也需要变更了。比如说,原本用来呈现Html的Presenter现在也需要用于呈现Pdf了,那么视图很有可能也需要变更。

android开发mvp,Android开发模式之MVP相关推荐

  1. mvvm模式和mvc的区别_Android 开发中的架构模式 -- MVC / MVP / MVVM

    预备知识 了解 Android 基本开发 看完本文可以达到什么程度 了解如何分析一个架构模式 掌握 MVC,MVP,MVVM 架构定义和实现 更多面试内容,面试专题,flutter视频 全套,音视频从 ...

  2. android filehelper,为AndroidStudio开发mvp插件(MvpHelper)

    如果觉得写mvp有点枯燥无味,我们可以做点 cool 的事情:做个 as 插件 help.png todo-mvp: 基础的MVP架构. todo-mvp-loaders:基于MVP架构的实现,在获取 ...

  3. 浅谈开发中的MVVM模式及与MVP和MVC的区别

    2019独角兽企业重金招聘Python工程师标准>>> 我记得前段时间分享了一篇文章< 浅谈Andorid开发中的MVP模式>(点击可跳转),反响不错,为了进一步介绍MV ...

  4. 【Android 应用开发】Android 返回堆栈管理 ( 默认启动模式 | 栈顶复用启动模式 | 栈内复用启动模式 | 单实例启动模式 | CLEAR_TOP 标识 )

    文章目录 I . 默认启动模式 ( standard ) II . 栈顶复用启动模式 ( singleTop ) III . 栈内复用启动模式 ( singleTask ) IV . 单实例启动模式 ...

  5. Android初级开发笔记-- activity启动模式的学习(1)

    第一次学习Android中一个很重要的概念,启动模式.文章记录的也只是一些入门知识,随着学习的深入还会有activity启动模式的学习(2)和(3). 下面分三个小点说一下对启动模式的理解区别以及如何 ...

  6. Android USB开发小结:host模式与accessory模式

    很早之前就想对Android USB的两种模式作个小结,但是一直没有空去搞,毕竟USB这块应该属于冷门方向,并且应用层能够做的比较少也很简单.最近刚好在做大疆无人机的二次开发,想着对USB连接检测这块 ...

  7. android rom 工作,Android ROM开发(4) bootloader 三种启动模式

    Andrew Huang 转载请注明作者及网址 HTC手机中用的bootloader称为HBoot,不知道是不是HTC Bootloader 之意,从官网的源码看这个bootloader不象是u-bo ...

  8. android项目小说阅读开发背景颜色,Android 小说阅读护眼模式

    Android 小说阅读护眼模式 实现方案:采用全局dialog 覆盖APP  悬浮在 其他APP之上,给dialog设置护眼色值 自定义护眼模式dialog public class EyeProt ...

  9. Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    本文转载自https://www.tianmaying.com/tutorial/AndroidMVC,原文作者周鸿博. 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开 ...

最新文章

  1. 交换机IEEE 802.1Q、VLAN ID、QoS之间的关系
  2. 微软企业库4.1学习笔记(三)企业库迁移和并行使用,以及企业库的扩展
  3. H3C LMI协议标准
  4. 在.net中读写XML方法的总结[转]
  5. yolov3安卓实现_从零实现YOLOv3
  6. C++11六大函数(构造函数,移动构造函数,移动赋值操作符,复制构造函数,赋值操作符,析构函数)
  7. python列表的特点_python基础(一)列表、集合和元组的基本特性
  8. 加快 DHTML 的一组技巧
  9. 使用MVC2模式创建新闻网站
  10. ip首部可选字段_IP报文格式及各字段意义
  11. 朴素贝叶斯分类器常用的三种条件概率模型:伯努利、多项式、高斯模型
  12. QQ防撤回9.0.2 软件 源码 源文件
  13. Fiddler自动回复器伪造回复
  14. 2015级计算机科学与技术2班班级博客大全
  15. 【FICO】标准成本、计划成本、实际成本、目标成本
  16. iphone4s在ios7下解决卡顿问题
  17. 【新知实验室】关于实时音视频
  18. java判断时间段是否交叉重叠
  19. Our replica set configuration is invalid or does not include us
  20. Java后端社招面试个人总结

热门文章

  1. 07-struts2提供的数据校验
  2. CSS 改变文本选中颜色
  3. 连接远程hbase长时间等待问题
  4. 详解Android源码的编译
  5. Bailian4143 和为给定数【排序+二分】
  6. HDU4548 美素数【水题】
  7. IE、Chrome、Firefox 三大浏览器对比
  8. Python 标准库 —— 邮件(email)与邮件服务器(smtplib)
  9. Tricks(三十三)—— 自定义 zipWithIndex
  10. 工具的使用 —— sublime