Android MVP模式实战教程

一、什么是MVP

在网上找了些资料,整理如下:

  MVP是模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块。

  模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;
  视图(View):负责界面数据的展示,与用户进行交互;
  主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来。

如下图所示,View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁。其中Presenter中同时持有Viwe层以及Model层的Interface的引用,而View层持有Presenter层Interface的引用。当View层某个界面需要展示某些数据的时候,首先会调用Presenter层的某个接口,然后Presenter层会调用Model层请求数据,当Model层数据加载成功之后会调用Presenter层的回调方法通知Presenter层数据加载完毕,最后Presenter层再调用View层的接口将加载后的数据展示给用户。这就是MVP模式的整个核心过程。

在MVP模式里通常包含4个要素:

(1)View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
     (2)View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
     (3)Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
     (4)Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。

二、MVP模式的使用

上面一张简单的MVP模式的UML图,从图中可以看出,使用MVP,至少需要经历以下步骤:

1.创建IPresenter接口,把所有业务逻辑的接口都放在这里,并创建它的实现PresenterCompl(在这里可以方便地查看业务功能,由于接口可以有多种实现所以也方便写单元测试)

2.创建IView接口,把所有视图逻辑的接口都放在这里,其实现类是当前的Activity/Fragment

3.由UML图可以看出,Activity里包含了一个IPresenter,而PresenterCompl里又包含了一个IView并且依赖了Model。Activity里只保留对IPresenter的调用,其它工作全部留到PresenterCompl中实现

4.Model并不是必须有的,但是一定会有View和Presenter

三、一个简单的MVP示例

实现一个简单的用户登录

效果如下:

先来看看java文件的目录结构:

1.Baen包

UserBean

package com.example.mvpe.bean; 

/**
 * Created by fendo on 2017/4/29.
 */ 

public class UserBean {
 private String username;
 private String userpwd; 

 public UserBean() {
 } 

 public UserBean(String username, String userpwd) {
 this.username = username;
 this.userpwd = userpwd;
 } 

 public String getUsername() {
 return username;
 } 

 public void setUsername(String username) {
 this.username = username;
 } 

 public String getUserpwd() {
 return userpwd;
 } 

 public void setUserpwd(String userpwd) {
 this.userpwd = userpwd;
 }
}

2.Model包

IUserModel类

package com.example.mvpe.model; 

import com.example.mvpe.bean.UserBean; 

/**
 * Created by fendo on 2017/4/29.
 */ 

public interface IUserModel { 

 void setSid(int cid);
 UserBean load(int sid);
 void setUsername(String username);
 void setUserpwd(String userpwd);
}

UserModelimp类

package com.example.mvpe.model; 

import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray; 

import com.example.mvpe.bean.UserBean; 

/**
 * Created by fendo on 2017/4/29.
 */ 

public class UserModelimp implements IUserModel{ 

 private static final String ACTIVITY_TAG="UserModelimp";
 private String username;
 private String userpwd;
 private int sid;
 private SparseArray<UserBean> su=new SparseArray<UserBean>(); 

 @Override
 public void setSid(int cid) {
 sid=cid;
 } 

 @Override
 public UserBean load(int sidy) {
 sid=sidy;
 UserBean ub=su.get(sid,new UserBean("not found",
  "not found"));
 return ub;
 } 

 @Override
 public void setUsername(String usernamey) {
 username=usernamey;
 } 

 @Override
 public void setUserpwd(String userpwdy) {
 userpwd=userpwdy;
 UserBean usb=new UserBean(username,userpwd);
 System.out.print(username+"----"+userpwd+"----"+sid);
 Log.d(UserModelimp.ACTIVITY_TAG, "Start_OK"+username+"----"+userpwd+"----"+sid);
 su.append(sid,usb);
 }
}

3.persenter包

UserPersenter类

package com.example.mvpe.presenter; 

import android.util.Log;
import android.view.View; 

import com.example.mvpe.bean.UserBean;
import com.example.mvpe.model.IUserModel;
import com.example.mvpe.model.UserModelimp;
import com.example.mvpe.view.IUserView; 

/**
 * Created by fendo on 2017/4/29.
 */ 

public class UserPersenter { 

 private static final String ACTIVITY_TAG="UserPersenter"; 

 private IUserView iUserView;
 private IUserModel iUserModel; 

 public UserPersenter(IUserView view){
 iUserView=view;
 iUserModel=new UserModelimp();
 } 

 public void saveuser(int sid,String username,String userpwd){
 iUserModel.setSid(sid);
 iUserModel.setUsername(username);
 iUserModel.setUserpwd(userpwd);
 } 

 public void loaduser(int sid){
 UserBean usb=iUserModel.load(sid);
 Log.d(ACTIVITY_TAG, "loaduser: "+usb.getUsername());
 iUserView.setUsername(usb.getUsername());
 iUserView.setUserpwd(usb.getUserpwd());
 } 

}

4.view包

IUserView类

package com.example.mvpe.view; 

import com.example.mvpe.bean.UserBean; 

/**
 * Created by fendo on 2017/4/29.
 */ 

public interface IUserView { 

 int getID(); 

 void setUsername(String username);
 void setUserpwd(String userpwd); 

 String getUserpwd();
 String getUsername();
}

UserActivity类

package com.example.mvpe.view; 

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText; 

import com.example.mvpe.R;
import com.example.mvpe.presenter.UserPersenter;
import android.view.View.OnClickListener;
import android.widget.Toast; 

/**
 * Created by fendo on 2017/4/29.
 */ 

public class UserActivity extends Activity implements OnClickListener,IUserView{ 

 private EditText userid;
 private EditText username;
 private EditText userpwd;
 private Button read;
 private Button write;
 private UserPersenter usp; 

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 usp=new UserPersenter(this);
 setContentView(R.layout.activity_main);
 findviewbyid();
 read.setOnClickListener(this);
 write.setOnClickListener(this);
 } 

 public void findviewbyid(){
 userid= (EditText) findViewById(R.id.userid);
 username= (EditText) findViewById(R.id.usertext);
 userpwd= (EditText) findViewById(R.id.userpwd);
 read= (Button) findViewById(R.id.read);
 write= (Button) findViewById(R.id.write);
 } 

 @Override
 public int getID() {
 return Integer.parseInt(userid.getText().toString());
 } 

 @Override
 public void setUsername(String usernamcc) {
 username.setText(usernamcc);
 } 

 @Override
 public void setUserpwd(String userpw) {
 userpwd.setText(userpw);
 } 

 @Override
 public String getUserpwd() {
 return userpwd.getText().toString();
 } 

 @Override
 public String getUsername() {
 return username.getText().toString();
 } 

 @Override
 public void onClick(View view) {
 switch (view.getId()) {
  case R.id.read :
  usp.loaduser(getID());
  Toast.makeText(getApplicationContext(), "点击了读"+getID(), Toast.LENGTH_SHORT).show(); 

  break;
  case R.id.write:
  usp.saveuser(getID(),getUsername(),getUserpwd());
  Toast.makeText(getApplicationContext(), "点击了存"+getID()+"--"+getUsername()+"--"+getUserpwd(), Toast.LENGTH_SHORT).show();
  break;
 }
 }
}

可以看到View只负责处理与用户进行交互,并把数据相关的逻辑操作都扔给了Presenter去做。而Presenter调用Model处理完数据之后,再通过IUserView更新View显示的信息。

下载:源码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android MVP模式ListView中嵌入checkBox的使用方法

    MVP模式 ListView中嵌入checkBox的使用 本文写的是一个小demo,如何在ListView中嵌入checkBox配合使用,本篇文章与前面的嵌入Button类似,同样的采用MVP模式的写代码,本次案例中会有几个小细节,我将会在案例中介绍. 程序基本框架如下: View层: MainActivity.java public class MainActivity extends AppCompatActivity implements ViewInter<MyBean>{ //Lis

  • 详解Android MVP开发模式

    本文主要讲解MVP开发模式以及具体实例. 一.简介 MVP(Model View Presenter)模式是著名的MVC(Model View Controller)模式的一个演化版本,目前它在Android应用开发中越来越重要了.初看起来我们会感觉增加了很多类接口代码看起来更加清晰. MVP模式可以分离显示层和逻辑层,所以功能接口如何工作与功能的展示可以实现分离,MVP模式理想化地可以实现同一份逻辑代码搭配不同的显示界面.不过MVP不是一个结构化的模式,它只是负责显示层而已,任何时候都可以在自

  • 完整的Android MVP开发之旅

    开发背景 最近是在做一个与健身相关的APP,里面有训练器模块基本功能是按照特点动作的演示和描述来引导用户完成训练.在第一个版本时由于没接触过些类项目与功能花了几周的时间大概1500行代码才完成这个功能, 当时虽然我已经尽量让代码表现的清晰,但是可以想像到当一个Activity中包含这么多代码是什么感觉.自己维护起来都难受. 先谈设计 有了前一次设计经验此次开发使用MVP.模块化.面向接口等概念,将整个训练器分为控制器.数据模型.音频.视图.可训练对象五个模块分别用以下接口表示: ITrainer

  • Android如何从实现到封装一个MVP详解

    前言 MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.下面这篇文章主要给大家介绍了关于Android从实现到封装MVP的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. MVP之间的联系 大概简单的解释就是M->module处理数据,V->Act显示界面,P->M和V沟通的渠道,即P用来将数据和界面联系到一起,这样子界面和数据就可以完全独立开来,Ac

  • 详解Android中的MVP架构分解和实现

    1.概述 传统的Android开发架构一般是MVC模式, Model:业务逻辑和实体模型 View:对应于布局文件 Controllor:对应于Activity 单独从逻辑看起来非常好,与我们做Web开发时,开发模式类似,但在实际开发中,View对应于布局文件,实际上关于该布局文件中的数据绑定的操作,事件处理的代码都在Activity中,Activity既像View又像Controller(MVVP架构中包括数据绑定),导致Activity中职责太重,耦合度大.修改和维护起来非常麻烦. 2.MV

  • 浅谈Android官方MVP架构解读

    综述 对于MVP (Model View Presenter)架构是从著名的MVC(Model View Controller)架构演变而来的.而对于Android应用的开发中本身可视为一种MVC架构.通常在开发中将XML文件视为MVC中的View角色,而将Activity则视为MVC中的Controller角色.不过更多情况下在实际应用开发中Activity不能够完全充当Controller,而是Controller和View的合体.于是Activity既要负责视图的显示,又要负责对业务逻辑的

  • Android开发:浅谈MVP模式应用与内存泄漏问题解决

    最近博主开始在项目中实践MVP模式,却意外发现内存泄漏比较严重,但却很少人谈到这个问题,促使了本文的发布,本文假设读者已了解MVP架构. MVP简介 M-Modle,数据,逻辑操作层,数据获取,数据持久化保存.比如网络操作,数据库操作 V-View,界面展示层,Android中的具体体现为Activity,Fragment P-Presenter,中介者,连接Modle,View层,同时持有modle引用和view接口引用 示例代码 Modle层操作 public class TestModle

  • 详解MVP模式在Android开发中的应用

    一.MVP介绍  随着UI创建技术的功能日益增强,UI层也履行着越来越多的职责.为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数据的可视化以及与用户的交互,同时让Model只关系数据的处理,基于MVC概念的MVP(Model-View-Presenter)模式应运而生. 在MVP模式里通常包含4个要素: (1)View:负责绘制UI元素.与用户进行交互(在Android中体现为Activity); (2)View interface:需要View实现的接口,Vie

  • Android中mvp模式使用实例详解

    MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller. 在MVC里,View是可以直接访问

  • Android MVP模式实战教程

    一.什么是MVP 在网上找了些资料,整理如下: MVP是模型(Model).视图(View).主持人(Presenter)的缩写,分别代表项目中3个不同的模块. 模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等: 视图(View):负责界面数据的展示,与用户进行交互: 主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来. 如下图所示,View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁

  • 从零搭建脚手架之集成Spring Retry实现失败重试和熔断器模式(实战教程)

    目录 背景 实战 添加依赖 启用重试 @Recover @CircuitBreaker 高级实战 方式一 @CircuitBreaker + RetryTemplate 方式二 @CircuitBreaker + @Retryable 参考 背景 在我们的大多数项目中,会有一些场景需要重试操作,而不是立即失败,让系统更加健壮且不易发生故障. 场景如下: 瞬时网络抖动故障 服务器重启 偶发死锁 某些上游的异常或者响应码,需要进行重试 远程调用 从数据库中获取或存储数据 以上皆为瞬时故障. 也会有一

  • Adapter模式实战之重构鸿洋集团的Android圆形菜单建行

    对于很多开发人员来说,炫酷的UI效果是最吸引他们注意力的,很多人也因为这些炫酷的效果而去学习一些比较知名的UI库.而做出炫酷效果的前提是你必须对自定义View有所理解,作为90的小民自然也不例外.特别对于刚处在开发初期的小民,对于自定义View这件事觉得又神秘又帅气,于是小民决定深入研究自定义View以及相关的知识点. 在此之前我们先来看看洋神的原版效果图: 记得那是2014年的第一场雪,比以往时候来得稍晚一些.小民的同事洋叔是一位资深的研发人员,擅长写UI特效,在开发领域知名度颇高.最近洋叔刚

  • Mybatis实战教程之入门到精通(经典)

    什么是mybatis MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象)映射成数据库中的记录. orm工具的基本思想 无论是用过的hibernate,mybatis,你都可以法相他们有一个共同点: 1. 从配置文件(通常是XML配置文件中)得到 ses

  • Python调用C# Com dll组件实战教程

    之前公司有套C# AES加解密方案,但是方案加密用的是Rijndael类,而非AES的四种模式(ECB.CBC.CFB.OFB,这四种用的是RijndaelManaged类),Python下Crypto库AES也只有这四种模式,进而Python下无法实现C# AES Rijndael类加密效果了. 类似于这种C# 能实现的功能而在Python下实现不了的,搜集资料有两种解决方案,第一种方式,使用IronPython 直接调用C# dll文件,教程网上很多,不在赘述了,这种方式有个缺点,用的是ir

随机推荐