Android MVP模式实战教程
作者:lfendo 发布时间:2023-09-05 13:16:54
一、什么是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显示的信息。
下载:源码
猜你喜欢
- 本文实例讲述了Android编程实现全局获取Context及使用Intent传递对象的方法。分享给大家供大家参考,具体如下:一、全局获取 C
- Android 列表组件 ListView列表组件是开发中经常用到组件,使用该组件在使用时需要为它提供适配器,由适配器提供来确定显示样式和显
- 在android开发中,一说起线程的使用,很多人马上想到new Thread(){...}.start()这种方式。这样使用当然可以,但是多
- 在Java的6.0版本中新增了concurrent包,这个包是用作线程同步的包,提供了很多工具类。其中定时器就是其中之一。近期在做一个项目,
- XmlTextWriter类允许你将XML写到一个文件中去。这个类包含了很多方法和属性,使用这些属性和方法可以使你更容易地处理XML。为了使
- 1、Java内存模型 Java虚拟机在执行程序时把它管理的内存分为若干数据区域,这些数据区域分布情况如下图所示:程序计数器:一块较小内存区域
- java读取文件内容,解析Json格式数据一、读取txt文件内容(Json格式数据) public static
- 本文实例为大家分享了Android实现View滑动效果的具体代码,供大家参考,具体内容如下一、View的滑动简介View的滑动是Androi
- 前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成
- 由Lombok的@AllArgsConstructor注解引发的错误需求:在Service实现中写了一个方法调用第三方接口同步数据。 功能代
- 一、单例模式我们先来看看两种创建单例模式的示例代码。1、饿汉式 饿汉式创建单例模式是在程序里面直接初始化了一个对象实例:class
- SpringBoot读取外置logback配置文件springboot项目可以读取外置配置文件,避免了修改配置文件需要重新打包部署的问题。部
- 本文实例讲述了Android编程简易实现XML解析的方法。分享给大家供大家参考,具体如下:首先创建在Android工程中创建一个Assets
- 本文实例讲述了Java深度复制功能与用法。分享给大家供大家参考,具体如下:写在前面:什么是深度复制?在Java里面,在创建一个对象,我们通常
- 前言这篇文章介绍如何使用Springboot+Junit+Mockito做单元测试,案例选取撮合交易的一个类来做单元测试。单元测试前先理解需
- 1. 在原有工程目录右键-> new ->Module->:2. 选择library:3. 一路next,最后finish
- JFormDesigner概述jformdesigner是一款功能强大的Swing设计工具,这是全面的程序,可帮助您创建Swing GUI,
- OSS.Http项目对于.Net Standard标准库的支持已经迁移完毕,OSS开源系列两个最底层的类库已经具备跨运行时支持的能力。由于O
- 目录环境依赖数据源方案一 使用 Spring Boot 默认配置方案二 手动创建脚本初始化使用 JdbcTemplate 操作实体对象DAO
- 前言在日常的开发中StringBuilder大家肯定都有用过,甚至用的很多。毕竟大家都知道一个不成文的规范,当需要高频的大量的构建字符串的时