Android MVP 架构模式详解
来源:互联网 发布:南航网络教学平台 编辑:程序博客网 时间:2024/06/05 14:42
MVP Sample
MVP架构模式入门案例,在众多案例中,应该算是比较规范和容易理解的案例了。示例代码请到我的github下载: https://github.com/li-xiaojun/MVPSample
MVP架构模式详解
11. MVP架构模式
- 概念解释
- MVP是Model(数据) View(界面) Presenter(表现层)的缩写,它是MVC架构的变种,强调Model和View的最大化解耦和单一职责原则
- Model:负责数据的来源和封装,比如网络请求类,数据库操作类以及java bean,如果有必要则提供接口暴露自己处理数据的状态和进度。
- View:负责UI相关,如布局UI的初始化,各种listener的设置。在Android中,我们通常写的Activity和Fragment就是属于View层;在web开发中,html则是View层。
- Controller:业务逻辑控制器,主要负责当获取到数据后对数据进行逻辑处理,然后将数据绑定到View上;比如:请求一个url,从网络获取到数据,进行解析javabean,然后各种set数据。对于控制器的概念大家很好理解,因为我们每天都在这样做,在Activity中请求数据然后更新UI。但是结合View的概念来看,很显然Activity和Fragment不但承担了View的任务,还负责完成的Controller的功能,随着业务功能的增多,Activity的代码越来越难以阅读和维护,这就是在Android中使用MVC的弊端,为了解决MVC模式下View层的臃肿,MVP模式应运而生。
- Presenter:专门从C独立出来的业务逻辑层,主要负责处理原先View层的业务逻辑,解决了Activity的臃肿问题,让Activity只负责处理UI,职责更加明确;并且将View层的业务逻辑抽取到P层之后,View层与Model层也实现了解耦;便于后期代码的扩展和维护,并且业务逻辑层独立后代码还得到很大的重用性
- 总结:MVC模式下,V和C纠缠不清,并且View和Model相互关联,而MVP模式下Model和VIew解耦,便于单元测试,项目维护,代码重用
先看看一个登录界面的业务逻辑和UI更新全部写在Activity的代码:
public class LoginActivity extends ActionBarActivity implements OnClickListener{ EditText etUsername,etPassword; Button btn_login; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etUsername = (EditText) findViewById(R.id.et_username); etPassword = (EditText) findViewById(R.id.et_password); btn_login = (Button) findViewById(R.id.btn_login); //设置点击事件 btn_login.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_login: String username = etUsername.getText().toString(); String password = etPassword.getText().toString(); if(checkInput(username,password)){ //提交登录 //执行登录请求 execLogin(username, password); } break; } } //执行登录请求 public void execLogin(String username,String password){ //执行登录请求的伪代码 HttpHelper helper = new HttpHelper(); helper.execRequest("http://www.baidu.com", new HttpCallback() { @Override public void onSuccess() { //提示登录成功 showLoginSuccess(LoginActivity.this); //保存登录相关数据,如登录的标记,用户的唯一标识 saveLoginData(); } @Override public void onFail() { //关闭登录对话框 hideLoginDialog(LoginActivity.this); //提示登录失败 showLoginFail(LoginActivity.this); } }); } //保存登录数据 public void saveLoginData(){ //保存登录相关的数据,代码略过... } //提示登录成功 public void showLoginFail(Context context){ Toast.makeText(context, "登录失败", 0).show(); } //提示登录失败 public void showLoginSuccess(Context context){ Toast.makeText(context, "登录成功", 0).show(); } //检查输入的合法性 private boolean checkInput(String username, String password) { boolean result = true; //1.检查为空 if(TextUtils.isEmpty(username) || TextUtils.isEmpty(password)){ Toast.makeText(this, "用户名或者密码不能为空!", 0).show(); result = false; } //2.检查长度 if(username.length()!=11){ Toast.makeText(this, "用户名长度不正确!", 0).show(); result = false; } if(password.length()<5){ Toast.makeText(this, "密码长度不能小于5位!", 0).show(); result = false; } return result; }}
现在抽取出LoginPresenter类,如下:
/** * 业务逻辑封装层 * @author lxj * */public class LoginPresenter { private ILoginView loginView; /** * 生命周期相关方法 */ public void onDestory(){ //do something to release and avoid memory leak; } public void onStart(){ //do something when onStart } public void onStop(){ //do something when onStop } public void onResume(){ //do something when onResume } public void onPause(){ //do something when onPause } public LoginPresenter(ILoginView loginView){ this.loginView = loginView; } //登录的方法 public void login(String username, String password) { if(!checkInput(username, password)){ return; } // 执行登录请求的伪代码 HttpHelper helper = new HttpHelper(); helper.execRequest("http://www.baidu.com", new HttpCallback() { @Override public void onSuccess() { // 需要UI展示,暴露接口 loginView.showLoginSuccess(); // 保存登录相关数据,如登录的标记,用户的唯一标识 saveLoginData(); } @Override public void onFail() { // 需要UI展示,暴露接口 loginView.showLoginFail(); } }); } private void saveLoginData() { //do something } // 检查输入的合法性 private boolean checkInput(String username, String password) { boolean result = true; // 1.检查为空 if (TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) { loginView.showInputNoNull(); result = false; } // 2.检查长度 if (username.length() != 11) { loginView.showUsernameLengthError(); result = false; } return result; }}
View和P解耦接口如下ILoginView:
public interface ILoginView { void showLoginSuccess(); void showLoginFail(); void showInputNoNull(); void showUsernameLengthError();}
最后的View层编写如下:
public class LoginActivity extends Activity implements OnClickListener,ILoginView{ EditText etUsername,etPassword; Button btn_login; private LoginPresenter loginPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etUsername = (EditText) findViewById(R.id.et_username); etPassword = (EditText) findViewById(R.id.et_password); btn_login = (Button) findViewById(R.id.btn_login); //设置点击事件 btn_login.setOnClickListener(this); //与loginPresenter交互 loginPresenter = new LoginPresenter(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_login: String username = etUsername.getText().toString(); String password = etPassword.getText().toString(); loginPresenter.login(username,password); break; } } public void showLoginSuccess(){ Toast.makeText(this, "登录成功", 0).show(); } public void showLoginFail(){ Toast.makeText(this, "登录失败", 0).show(); } public void showInputNoNull(){ Toast.makeText(this, "用户名和密码不能为空!", 0).show(); } public void showUsernameLengthError(){ Toast.makeText(this, "用户名长度不正确!", 0).show(); } public void hideLoginDialog(){ if(progressDialog!=null){ progressDialog.dismiss(); } } @Override protected void onResume() { super.onResume(); loginPresenter.onResume(); } @Override protected void onStart() { super.onStart(); loginPresenter.onStart(); } @Override protected void onStop() { super.onStop(); loginPresenter.onStop(); } @Override protected void onPause() { super.onPause(); loginPresenter.onPause(); } @Override protected void onDestroy() { super.onDestroy(); loginPresenter.onDestory(); }}
总结:MVP只是给我们提出了分层解耦的思想,并没有一个固定的实现。Google虽然出了官方的MVP实现示例,但是并没有太多人去跟随,很多公司在对Presenter层都有自己的理解,此处的案例相对来说比较规范,对MVP三层都有清晰的解耦和实现,在茫茫开源项目中,算是比较好的容易理解的上手项目了。
0 0
- Android MVP 架构模式详解
- Android中MVP架构模式详解
- Android Mvp+DataBinding架构模式详解
- MVP架构模式详解
- MVP架构模式详解
- Android MVP开发模式 google 官方Mvp架构详解
- android-MVP架构模式
- Android|MVP架构模式
- Android MVP 模式 详解
- Android MVP模式详解
- Android架构:MVP模式实例
- Android mvp 设计模式目录架构设计
- Android开发App架构MVP模式
- Android架构模式:MVC & MVP & MVVM
- Android之MVP架构模式_
- Android开发中的MVP架构详解
- Android开发之MVP架构详解
- Android MVC和MVP架构的详解
- 使用 C# 获取当前用户的SID
- c++作业7
- Hadoop-2.4.1源码分析--由HDFS心跳检测想到的Keepalived
- c++第七次作业
- Codeforces 300A:Array(易错)
- Android MVP 架构模式详解
- EventBus3.0使用初体验
- sudo apt-get update时遇到以下问题
- C++第七次作业
- 《Vim Pratical》学习笔记
- Android_Handler
- python的get方式提交请求
- 控件和布局的XML 属性:step one
- localStorage也可以限时保存登录信息