Android中MVP的初步认识与简单用法

概述

认识MVP模式

MVP 模式实际上指的是 Model-View-Presenter 主要的目的是为了划分各个模块的负责区域,分工明确,使代码清晰了很多。也是为了减少 Activity 中代码,使其没有那么臃肿,提高测试性,主要的分工如下:

View 主要是负责显示数据和与用户进行交互,这可以是一个 Activity 或者是一个 Fragment,一个 android.view.View 或者是一个 Dialog。

Model 是数据源层,负责对数据进行存储,检索之类的操作。

Present 是 View 和 Model 进行交互的中间桥梁,负责 Model 和 View 两者之间的处理,也就是说从Model中获取的数据然后传递给 View,起到一个中间人的作用,也是在 MVP 模式中处理复杂逻辑的地方,后台任务也是它负责的。

为什么要使用 MVP 模式?

使其尽可能的简单

  • 把复杂的任务分解成许多个简单小任务来执行
  • 分解成的小任务 bug 比较少
  • 减少测试时间

后台任务不和 Activity 关联

当你需要写一个 Activity,Fragment 或者一个自定义 View 的时候,你可以将所有和后台相关的方法放在一个外部类或者静态类中,这样你的后台任务就不会和Activity有关联,也不存在内存的泄漏的问题。

MVP 模式说明

其实在 MVP 中 Activity 对应的就是 View,把 Activity 中的 UI 逻辑抽象成 View 接口,在 View 中进行 UI 设计和简单的逻辑处理,Model 是业务逻辑和实体模型的实现,Presenter 负责完成View于Model间的交互(在这里进行复杂的逻辑处理),图片来自这里

使用 MVP 模式

由上图可以看出,在 MVP 模式中 Model 和 View 是不能直接交互的,而是通过 Presenter这个中间桥梁进行交互, MVP 和 MVC 模式最大的区别就在于此。也可以看出View和Presenter是一对一的关系,Model 可以为不同的 Presenter 提供数据服务。一般来说 Presenter 与 View 的交互是通过接口来进行的,这样有利于添加单元测试。

MVP 实例讲解

说了那么多还是用一个 Demo 来说一下,这样就比较好理解了。就用最简单的例子来说吧,做的是一个登录界面,输入账号和密码,账号密码输入正确的话则提示登录成功,反之则登录失败。效果图如下

登陆界面

项目结构

项目结构

从项目结构可以直接看出来,首先必须是要有实体类,然后就是 Model 的接口和实例,里面便是业务类中的实现方法,还有就是 View 的接口和实例,里面是负责 UI 的绘制和用户进行交互的逻辑,最后便是 Presenter,这里面作为 Model 和 View 的中间协调部分,负责两者之间的业务逻辑处理,复杂的逻辑处理一般都在这里进行编写。

实体类

首先是实体类的代码,实体类是必须有的就不用多说了

package com.example.xiaozhang.userloginactivity;
/** 
* Created by xiaozhang on 2016/11/3.
*/
//创建实体类,实体类必须有的!!!
public class UserBean {  
private String UserName;  
private String PassWord;  
public String getUserName() { 
return UserName;
}  
public void setUserName(String userName) {  
UserName = userName;  
 }  
public String getPassWord() {   
return PassWord; 
 }  
public void setPassWord(String passWord) {
PassWord = passWord;
  }
 }

Model

在 Model 中有一个业务的接口,处理逻辑交给 Presenter 就行了。

package com.example.xiaozhang.userloginactivity.Model;
import com.example.xiaozhang.userloginactivity.UserBean;
/** 
* Created by xiaozhang on 2016/11/3. 
*/
//Model接口------业务逻辑或者实体型接口
public interface IUserLoginModel {  
 void Login(UserBean mUserBean);
}

为了能让点击登录后有提示,需要一个自定义 Listener 接口用来显示在屏幕上作为提醒,代码逻辑如下

package com.example.xiaozhang.userloginactivity.Model;
/** 
* Created by xiaozhang on 2016/11/3. 
*/
public interface IUserLoginListener {  
 void loginListener(boolean status);
}

最后是Model类中的业务类的逻辑编写

package com.example.xiaozhang.loginactivity.Model;
import com.example.xiaozhang.loginactivity.UserBean;
/**
 *
 Created by xiaozhang on 2016/11/3. 
*/
public class UserLoginModel implements IUserLoginModel {  
private String UserName;
private String PassWord;  
private IUserLoginListener LoginListener;  
public UserLoginModel(IUserLoginListener loginListener){  
  this.LoginListener = loginListener;
  }  
@Override public void Login(UserBean mUserBean) {  
  boolean status = false;   
UserName = mUserBean.getUserName();    
PassWord = mUserBean.getPassWord();   
 if ("admin".equals(UserName)&&"123456".equals(PassWord))        
status = true;   
 LoginListener.loginListener(status); 
 }
}

View

View 和 Presenter 交互是通过接口的行形式,不过在写这个接口之前需要想一想需要实现的功能有哪些。
登录功能上肯定要有用户名和密码

String getUserName();
String getPassWord();

重置功能上也是要有清除用户名和密码

void clearUserName();
void clearPassWord();

还有就是点击登录按钮后显示是否成功登录的消息提示

void showMessage(String Message);

整合一下就是一个 View 接口的所有实现代码了

package com.example.xiaozhang.userloginactivity.View;
/**
 * Created by xiaozhang on 2016/11/3.
 */
public interface IUserLoginActivity {  
String getUserName();  
String getPassWord();  
void clearUserName();  
void clearPassWord(); 
 void showMessage(String Message);
}

后面就是写实现类了,前面说过了 Activity 对应的就是 View 的实现类,所以在 Activity中写实现类的逻辑

package com.example.xiaozhang.userloginactivity.View;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;import android.widget.EditText;
import android.widget.Toast;
import com.example.xiaozhang.userloginactivity.Presenter.UserLoginPresenter;
import com.example.xiaozhang.userloginactivity.R;
public class UserLoginActivity extends AppCompatActivity implements IUserLoginActivity { 
 private EditText mInputUserName;  
private EditText mInputPassWord;  
private Button mLogin;  
private Button mReset;  
//这里需要注意下,没有 Presenter 的话前面这些都白写了,所以一定要创建实例!
private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);
  @Override  
protected void onCreate(Bundle savedInstanceState) {    
super.onCreate(savedInstanceState);   
 setContentView(R.layout.activity_main);  
  initView();  
}  
private void initView() {    
mInputUserName = (EditText) findViewById(R.id.edit_input_Account);  
mInputPassWord = (EditText) findViewById(R.id.edit_input_PassWord);   
 mLogin = (Button) findViewById(R.id.btn_Login);  
 mReset = (Button) findViewById(R.id.btn_Reset); 
 mLogin.setOnClickListener(new View.OnClickListener() {  
    @Override public void onClick(View view) {     
   //复杂的逻辑交给Presenter       
 mUserLoginPresenter.login();   
   }   
 });   
 mReset.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View view) {  
      //复杂的逻辑交给presenter
        mUserLoginPresenter.Reset();  
    }   
 }); 
 }  
@Override public String getUserName() {  
  return mInputUserName.getText().toString(); 
 }  
@Override public String getPassWord() { 
   return mInputPassWord.getText().toString();
  }  
@Override public void clearUserName() {
    mInputUserName.setText(""); 
 } 
 @Override public void clearPassWord() { 
   mInputPassWord.setText(""); 
 }
  @Override  public void showMessage(String Message) {  
  Toast.makeText(this, Message, Toast.LENGTH_LONG).show();
  }
}

Presenter

前面也提到了 Presenter 是 View 和 Model 进行交互的中间桥梁,这也要看你在你的代码里需要实现的是什么功能,在这里实现的登录和重置功能的实现以及点击登录后是否能成功登录出现的提示消息

package com.example.xiaozhang.userloginactivity.Presenter;
import com.example.xiaozhang.userloginactivity.Model.IUserLoginModel;
import com.example.xiaozhang.userloginactivity.Model.IUserLoginListener;
import com.example.xiaozhang.userloginactivity.Model.UserLoginModel;
import com.example.xiaozhang.userloginactivity.UserBean;
import com.example.xiaozhang.userloginactivity.View.IUserLoginActivity;
/** 
* Created by xiaozhang on 2016/11/3. 
*/
public class UserLoginPresenter  implements IUserLoginListener{  
private IUserLoginModel mIUserLoginModel; 
 private IUserLoginActivity mIUserLoginActivity; 
 public UserLoginPresenter(IUserLoginActivity mIULoginActivity) {    
this.mIUserLoginActivity = mIULoginActivity;  //这里命名后来发现不好区分,所以改了。。
  mIUserLoginModel = new UserLoginModel(this);  
}  
public void login() { 
 UserBean mUserBean = new UserBean();    
mUserBean.setUserName(mIUserLoginActivity.getUserName());    
mUserBean.setPassWord(mIUserLoginActivity.getPassWord());    
mIUserLoginModel.Login(mUserBean); 
 } 
 public void Reset() { 
   mIUserLoginActivity.clearPassWord();   
 mIUserLoginActivity.clearUserName(); 
 }  
@Override public void loginListener(boolean status) {  
  String Message;   
 if (status)      
Message= "登录成功";  
  else    
  Message= "登录失败,请检查账号密码是否正确";    
mIUserLoginActivity.showMessage(Message);  }
}

总结

以上便是我对MVP的初步认识,毕竟自己也是刚接触这个不久,所以写的不好还请指导。对于刚接触到MVP模式还是有很多的问题,只能参考写出这么一个简单的Demo,后面也会从接触到的项目中学习到MVP的用法,到时候也会写出来和大家分享。

参考资料

对MVP说的比较详细的文章
浅谈MVP
Android MVP模式 简单易懂的介绍方式

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,183评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,850评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,766评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,854评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,871评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,457评论 1 311
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,999评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,914评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,465评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,543评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,675评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,354评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,029评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,514评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,616评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,091评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,685评论 2 360

推荐阅读更多精彩内容