MVP Architecture on Android
原文:http://blog.csdn.net/lmj623565791/article/details/46596109
一、概述
对于MVP(Model View Presenter),大多数人都能说出一二:“MVC的演化版本”,“让Model和View完全解耦”等等。本篇博文仅是为了做下记录,提出一些自己的看法,和帮助大家如何针对一个Activity页面去编写针对MVP风格的代码。
对于MVP,我的内心有一个问题:
为何这个模式出来后,就能被广大的Android的程序员接受呢?
问了些程序员,他们对于MVP的普遍的认识是:“代码很清晰,不过增加了很多类”。我在第一次看到MVP的时候,看了一个demo,看完以后觉得非常nice(但是回过头来,自己想个例子写,就头疼写不出来,当然这在后文会说)。nice的原因还是因为,这个模式的确让代码的清晰度有了很大的提升。
那么,提升一般都是对比出来的,回顾下,没有应用MVP的代码结构。很多人说明显是MVC么:
- View:对应于布局文件
- Model:业务逻辑和实体模型
- Controllor:对应于Activity
看起来的确像那么回事,但是细细的想想这个View对应于布局文件,其实能做的事情特别少,实际上关于该布局文件中的数据绑定的操作,事件处理的代码都在Activity中,造成了Activity既像View又像Controller(当然了Data-Binder的出现,可能会让View更像View吧)。这可能也就是为何,在https://github.com/konmik/konmik.github.io/wiki/Introduction-to-Model-View-Presenter-on-Android中有一句这样的话:
Most of the modern Android applications just use View-Model architecture,everything is connected with Activity.
而当将架构改为MVP以后,Presenter的出现,将Actvity视为View层,Presenter负责完成View层与Model层的交互。现在是这样的:
- View 对应于Activity,负责View的绘制以及与用户交互
- Model 依然是业务逻辑和实体模型
- Presenter 负责完成View于Model间的交互
ok,先简单了解下,文中会有例子到时候可以直观的感受下。
小总结下,也就是说,之所以让人觉得耳目一新,是因为这次的跳跃是从并不标准的MVC
到MVP
的一个转变,减少了Activity的职责,简化了Activity中的代码,将复杂的逻辑代码提取到了Presenter中进行处理。与之对应的好处就是,耦合度更低,更方便的进行测试。借用两张图(出自:https://github.com/konmik/konmik.github.io/wiki/Introduction-to-Model-View-Presenter-on-Android),代表上述的转变:
转变为:
二、MVP 与 MVC 区别
ok,上面说了一堆理论,下面我们还是需要看一看MVC与MVP的一个区别,请看下图(来自:本文):
其实最明显的区别就是,MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成。还有一点就是Presenter与View之间的交互是通过接口的(代码中会体现)。
还有一堆概念性的东西,以及优点就略了,有兴趣自行百度。下面还是通过一些简单的需求来展示如何编写MVP的demo。
三、Simple Login Demo
效果图:
看到这样的效果,先看下完工后的项目结构:
ok,接下来开始一步一步的编写思路。
(一)Model
首先实体类User不用考虑这个肯定有,其次从效果图可以看到至少有一个业务方法login(),这两点没什么难度,我们首先完成:
package com.zhy.blogcodes.mvp.bean;/*** Created by zhy on 15/6/18.*/
public class User
{private String username ;private String password ;public String getUsername(){return username;}public void setUsername(String username){this.username = username;}public String getPassword(){return password;}public void setPassword(String password){this.password = password;}
}
package com.zhy.blogcodes.mvp.biz;/*** Created by zhy on 15/6/19.*/
public interface IUserBiz
{public void login(String username, String password, OnLoginListener loginListener);
}
import com.zhy.blogcodes.mvp.bean.User;/*** Created by zhy on 15/6/19.*/
public class UserBiz implements IUserBiz
{@Overridepublic void login(final String username, final String password, final OnLoginListener loginListener){//模拟子线程耗时操作new Thread(){@Overridepublic void run(){try{Thread.sleep(2000);} catch (InterruptedException e){e.printStackTrace();}//模拟登录成功if ("zhy".equals(username) && "123".equals(password)){User user = new User();user.setUsername(username);user.setPassword(password);loginListener.loginSuccess(user);} else{loginListener.loginFailed();}}}.start();}
}
package com.zhy.blogcodes.mvp.biz;import com.zhy.blogcodes.mvp.bean.User;/*** Created by zhy on 15/6/19.*/
public interface OnLoginListener
{void loginSuccess(User user);void loginFailed();
}
实体类不用说,至于业务类,我们抽取了一个接口,一个实现类这也很常见~~login方法,一般肯定是连接服务器的,是个耗时操作,所以我们开辟了子线程,Thread.sleep(2000)模拟了耗时,由于是耗时操作,所以我们通过一个回调接口来通知登录的状态。
其实这里还是比较好写的,因为和传统写法没区别。
(二) View
上面我们说过,Presenter与View交互是通过接口。所以我们这里需要定义一个ILoginView
,难点就在于应该有哪些方法,我们看一眼效果图:
可以看到我们有两个按钮,一个是login,一个是clear;
login说明了要有用户名、密码,那么对应两个方法:
String getUserName();String getPassword();
再者login是个耗时操作,我们需要给用户一个友好的提示,一般就是操作ProgressBar,所以再两个:
void showLoading();void hideLoading();
login当然存在登录成功与失败的处理,我们主要看成功我们是跳转Activity,而失败可能是去给个提醒:
void toMainActivity(User user);void showFailedError();
ok,login这个方法我们分析完了~~还剩个clear那就简单了:
void clearUserName();void clearPassword();
综上,接口完整为:
package com.zhy.blogcodes.mvp.view;import com.zhy.blogcodes.mvp.bean.User;/*** Created by zhy on 15/6/19.*/
public interface IUserLoginView
{String getUserName();String getPassword();void clearUserName();void clearPassword();void showLoading();void hideLoading();void toMainActivity(User user);void showFailedError();}
有了接口,实现就太好写了~~~
总结下,对于View的接口,去观察功能上的操作,然后考虑:
- 该操作需要什么?(getUserName, getPassword)
- 该操作的结果,对应的反馈?(toMainActivity, showFailedError)
- 该操作过程中对应的友好的交互?(showLoading, hideLoading)
下面贴一下我们的View的实现类,哈,其实就是Activity,文章开始就说过,MVP中的View其实就是Activity。
package com.zhy.blogcodes.mvp;import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;import com.zhy.blogcodes.R;
import com.zhy.blogcodes.mvp.bean.User;
import com.zhy.blogcodes.mvp.presenter.UserLoginPresenter;
import com.zhy.blogcodes.mvp.view.IUserLoginView;public class UserLoginActivity extends ActionBarActivity implements IUserLoginView
{private EditText mEtUsername, mEtPassword;private Button mBtnLogin, mBtnClear;private ProgressBar mPbLoading;private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_user_login);initViews();}private void initViews(){mEtUsername = (EditText) findViewById(R.id.id_et_username);mEtPassword = (EditText) findViewById(R.id.id_et_password);mBtnClear = (Button) findViewById(R.id.id_btn_clear);mBtnLogin = (Button) findViewById(R.id.id_btn_login);mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading);mBtnLogin.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v){mUserLoginPresenter.login();}});mBtnClear.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v){mUserLoginPresenter.clear();}});}@Overridepublic String getUserName(){return mEtUsername.getText().toString();}@Overridepublic String getPassword(){return mEtPassword.getText().toString();}@Overridepublic void clearUserName(){mEtUsername.setText("");}@Overridepublic void clearPassword(){mEtPassword.setText("");}@Overridepublic void showLoading(){mPbLoading.setVisibility(View.VISIBLE);}@Overridepublic void hideLoading(){mPbLoading.setVisibility(View.GONE);}@Overridepublic void toMainActivity(User user){Toast.makeText(this, user.getUsername() +" login success , to MainActivity", Toast.LENGTH_SHORT).show();}@Overridepublic void showFailedError(){Toast.makeText(this,"login failed", Toast.LENGTH_SHORT).show();}
}
对于在Activity中实现我们上述定义的接口,是一件很容易的事,毕竟接口引导我们去完成。
最后看我们的Presenter。
(三)Presenter
Presenter是用作Model和View之间交互的桥梁,那么应该有什么方法呢?
其实也是主要看该功能有什么操作,比如本例,两个操作:login和clear。
package com.zhy.blogcodes.mvp.presenter;import android.os.Handler;import com.zhy.blogcodes.mvp.bean.User;
import com.zhy.blogcodes.mvp.biz.IUserBiz;
import com.zhy.blogcodes.mvp.biz.OnLoginListener;
import com.zhy.blogcodes.mvp.biz.UserBiz;
import com.zhy.blogcodes.mvp.view.IUserLoginView;/*** Created by zhy on 15/6/19.*/
public class UserLoginPresenter
{private IUserBiz userBiz;private IUserLoginView userLoginView;private Handler mHandler = new Handler();public UserLoginPresenter(IUserLoginView userLoginView){this.userLoginView = userLoginView;this.userBiz = new UserBiz();}public void login(){userLoginView.showLoading();userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener(){@Overridepublic void loginSuccess(final User user){//需要在UI线程执行mHandler.post(new Runnable(){@Overridepublic void run(){userLoginView.toMainActivity(user);userLoginView.hideLoading();}});}@Overridepublic void loginFailed(){//需要在UI线程执行mHandler.post(new Runnable(){@Overridepublic void run(){userLoginView.showFailedError();userLoginView.hideLoading();}});}});}public void clear(){userLoginView.clearUserName();userLoginView.clearPassword();}}
注意上述代码,我们的presenter完成二者的交互,那么肯定需要二者的实现类。大致就是从View中获取需要的参数,交给Model去执行业务方法,执行的过程中需要的反馈,以及结果,再让View进行做对应的显示。
参考链接:
MVP Architecture on Android相关推荐
- android中的mvp模式怎么定义,详解MVP模式在Android开发中的应用
一.MVP介绍 随着UI创建技术的功能日益增强,UI层也履行着越来越多的职责.为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数据的可视化以及与用户的交互,同时让Mode ...
- mvp模式复用android,MVP模式
简称:MVP 全称:Model-View-Presenter :MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供 ...
- MVP模式在Android实际项目中的应用和优化
注:本文阅读需要对MVP模式有基本了解. MVP模式已经出现有很长一段时间了,但是火起来是这两年的事情. 关于MVP的概览,介绍,乃至于教程,Demo,实例,网上都有很多,我也有一篇文章专门收录了一些 ...
- android mvc mvp 区别,谈谈Android框架 MVC、MVP、MVVM的区别
今天写写Android的MVC.MVP.MVVP三个框架的对比,并加深自己对这三个框架的理解. 548b9bea8dc18.gif 一 . MVC:Model-View-Controller MVC全 ...
- android+mvp+登录案例,android mvp实现登录
android的mvp是什么呢? Model:用于数据的增删改查等,也包括一些数据对象 ,主要用来处理一些业务操作. View:用于界面的显示与用户操作的接收,在Android里面View通常就是Ac ...
- android MVP连接服务器,Android之MVP模式实现登陆和网络数据加载
MVP简介 相信你们对 MVC 都是比较熟悉了:M-Model-模型.V-View-视图.C-Controller-控制器,MVP做为MVC的演化版本,也是做为用户界面(用户层)的实现模式,那么相似的 ...
- Flux Architecture on Android
英文原文:http://lgvalle.xyz/2015/08/04/flux-architecture/ 要为安卓应用找到一个好的架构不是一件容易的事情.谷歌似乎不太在乎这个事情,因此在设计模式上, ...
- android mvp 利弊,android mvp模式有什么弊端 - 什么是android mvp模式,android mvp模式有什么弊端...
android mvp模式有什么弊端 才开始学习使用MVP时,看到大家说了很多MVP的优点,代码复用,条理清晰等等.不过我改下来发现,MVP在我看来,最大的优点还是代码解耦,逻辑清晰,至于代码复用,暂 ...
- android mvp 代码范例,Android MVP开发模式有案例和源码,反正我能看懂的MVP
丁先森 博客园 MVP 理论知识 在MVP 架构中跟MVC类似的是同样也分为三层. Activity 和Fragment 视为View层,负责处理 UI. Presenter 为业务处理层,既能调用U ...
最新文章
- 被英特尔“冷落”的Knights Mill 悄然发布了
- vue 打印 canvas 显示空白
- 要管理此计算机上的用户账户,win10用户账户控制 你要允许此应用 若要继续请输入管理员密码...
- 协作通信-af df的matlab仿真,协作通信-AF、DF的MATLAB仿真(解压密码yuema1086)
- JFreeChart 1.0.6 用户开发指南(中文)
- 004 排序(冒泡快排)
- 常用类回顾之(String类)
- mybatis学习(51):扩展集
- PSD分层电商促销模板|换季大促销,不怕老板催你做海报了
- android firefox 版本,Android版本Firefox初期预览版发布
- paip.python错误解决9
- STC学习:非易失存储器
- MySQL命令行客户端(一)客户端选项
- like语句太慢 sqlserver_SQLSERVER查询速度慢的原因收集以及优化建议
- 因子分析 factor analysis (一 ):模型的理论推导
- HTML基本结构及基本标签
- input密码框显示与隐藏
- MXNet对含隐藏状态的循环神经网络(RNN)的实现
- PHP学习笔记(二)——行云博客
- scroller基础知识点
热门文章
- 领导驾驶舱是怎么做出来的?
- 硬盘检测工具+linux,linux硬盘检测工具:Smartmontools使用指南
- linux 将sda分区扩容
- Jsp Servlet 学生公寓管理系统
- 北京大学推免2020计算机,《北京大学2020年接收外校推免生分析报告(一)》——哪些学校更受青睐?...
- sdjzu 1022
- 五大影响记忆力的日常习惯
- 登录超时连不上信息服务器,我的侠客进不去怎么办 服务器登录连接超时请稍后再试解决方法...
- 小米业绩再创季度新高,股价或再次上涨,米粉或实现赚一倍的愿望
- python中cv是什么_python里面cv是什么意思