【Android】MVP架构
MVP架构简介
MVP(Model-View-Presenter)是一种常见的软件架构模式,尤其在Android应用开发中被广泛使用。它将应用程序分为三层:Model、View 和 Presenter,以实现职责分离,提高代码的可维护性和可测试性。
1. Model(模型)
- 定义:负责处理应用程序的数据逻辑,包括与数据库、网络、API等数据源的交互。
- 职责:提供数据,并将其返回给 Presenter,不涉及任何UI相关逻辑。
2. View(视图)
- 定义:负责展示用户界面,接收用户的输入并将其传递给 Presenter。
- 职责:展示由 Presenter 提供的数据,并根据用户操作调用 Presenter 的方法。View 层不直接处理逻辑,只展示内容。
3. Presenter(演示者)
- 定义:作为 View 和 Model 之间的桥梁,负责处理逻辑和协调数据流。
- 职责:
- 从 View 接收用户输入,调用 Model 获取数据。
- 将数据处理结果返回给 View 以更新UI。
- Presenter 不直接操作UI,而是通过接口与 View 进行交互。
MVP与MVC的区别
1. 核心组成部分的区别
- MVP:
- Model:负责数据逻辑的处理,类似于MVC中的Model。
- View:展示数据、处理用户界面交互,但不会直接处理业务逻辑,所有逻辑都交给 Presenter。
- Presenter:作为中间层,负责从 Model 获取数据并处理业务逻辑,然后将数据传递给 View。Presenter 直接与 View 交互。
- MVC:
- Model:同样负责数据逻辑的处理,与 MVP 中的 Model 类似。
- View:展示数据并处理用户输入,但可以直接与 Controller 进行交互。
- Controller:控制器响应用户的输入,更新 Model 和 View,但它不直接操作 View,而是通知 View 自行更新。
2. 交互方式的区别
- MVP:
- View 与 Model 之间没有直接交互。View 只负责调用 Presenter,Presenter 是唯一能与 Model 交互的部分,然后 Presenter 将结果返回给 View 来更新界面。
- 双向交互:View 和 Presenter 是双向交互的,View 可以调用 Presenter,Presenter 也可以调用 View 来更新UI。
- MVC:
- View 可以直接与 Model 交互。在MVC中,View可以直接从Model中获取数据,虽然一般情况下是通过Controller来协调。
- 单向交互:View 和 Controller 之间的交互通常是单向的,用户的输入会通过 View 传递给 Controller,Controller 再更新 Model,最后通知 View 更新UI。
3. 视图的控制权
- MVP:
- Presenter 控制视图:在MVP模式中,Presenter 负责处理所有业务逻辑,并决定何时以及如何更新 View。View 不进行逻辑处理,只是被动地展示数据。
- MVC:
- Controller 充当中介:在MVC中,Controller 只是起到协调作用,它不会主动控制 View 的更新,通常会将新的数据传递给 View 或通知 View 进行自我更新。
MVP架构优点
-
View层与Model层完全分离
-
所有View层 和 Model层 逻辑交互都在Presenter
-
后续扩展性/可维护性强,M层(负责数据业务模型), P层(负责M层与V层的交互逻辑)
-
定位修改Bug方便:
如果是修改界面交互相关的,直接找V层修改
如果是修改数据业务逻辑,直接找M层修改

MVP架构特点
关系:
-
View收到用户的操作
-
View把用户的操作,交给Presenter
-
Presenter直接操作Model进行业务逻辑处理
-
Model处理完毕后,通知Presenter
-
Presneter收到通知后,在去更新View
方式:
是双向的通信方式
优点:
- View层与Model层完全分离
- 所有的逻辑交互都在Presenter
- MVP分层较为严谨


示例
- Model (数据层)
Model 负责处理数据逻辑,判断用户名和密码是否正确。
public class LoginModel {// 模拟用户登录数据public boolean validateUser(String username, String password) {// 简单模拟,假设用户名为"user",密码为"password"时登录成功return username.equals("user") && password.equals("password");}
}
- View (视图层)
View 负责显示界面,并将用户的输入传递给 Presenter,它不会直接处理业务逻辑。
public interface LoginView {// 展示登录成功的信息void showLoginSuccess();// 展示登录失败的信息void showLoginError();// 获取用户名String getUsername();// 获取密码String getPassword();
}
具体实现:
public class LoginActivity extends AppCompatActivity implements LoginView {private EditText usernameEditText, passwordEditText;private Button loginButton;private LoginPresenter presenter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);usernameEditText = findViewById(R.id.username);passwordEditText = findViewById(R.id.password);loginButton = findViewById(R.id.login_button);presenter = new LoginPresenter(this, new LoginModel());loginButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {presenter.onLoginClicked();}});}@Overridepublic void showLoginSuccess() {Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();}@Overridepublic void showLoginError() {Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show();}@Overridepublic String getUsername() {return usernameEditText.getText().toString();}@Overridepublic String getPassword() {return passwordEditText.getText().toString();}
}
- Presenter (逻辑层)
Presenter 负责处理业务逻辑,并将数据从 Model 传递到 View。
public class LoginPresenter {private LoginView view;private LoginModel model;public LoginPresenter(LoginView view, LoginModel model) {this.view = view;this.model = model;}// 当用户点击登录按钮时调用public void onLoginClicked() {String username = view.getUsername();String password = view.getPassword();// 通过 Model 验证用户输入if (model.validateUser(username, password)) {view.showLoginSuccess();} else {view.showLoginError();}}
}
- 布局文件 (activity_login.xml)
简单的登录界面,包含输入框和按钮。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><EditTextandroid:id="@+id/username"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="用户名" /><EditTextandroid:id="@+id/password"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="密码"android:inputType="textPassword" /><Buttonandroid:id="@+id/login_button"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="登录" />
</LinearLayout>
工作流程:
- 用户在
LoginActivity中输入用户名和密码并点击登录按钮。 LoginActivity作为 View 层,将用户输入传递给LoginPresenter。LoginPresenter从 View 获取用户名和密码,并调用LoginModel来验证用户输入。LoginModel验证输入是否正确,然后将结果返回给LoginPresenter。LoginPresenter根据验证结果通知LoginActivity更新UI,显示登录成功或失败的消息。
已经到底啦!!
相关文章:
【Android】MVP架构
MVP架构简介 MVP(Model-View-Presenter)是一种常见的软件架构模式,尤其在Android应用开发中被广泛使用。它将应用程序分为三层:Model、View 和 Presenter,以实现职责分离,提高代码的可维护性和可测试性。 …...
Web服务器之Nginx
Nginx(发音为Engine X)是一款开源的高性能HTTP和反向代理服务器,同时也提供了IMAP/POP3/SMTP服务。由伊戈尔赛索耶夫(Igor Sysoev)为俄罗斯访问量第二的Rambler.ru站点开发,Nginx自发布以来,凭借…...
【大模型实战篇】大模型分词算法Unigram及代码示例
1. 算法原理介绍 与 BPE 分词(参考《BPE原理及代码示例》)和 WordPiece 分词(参考《WordPiece原理及代码示例》)不同,Unigram 分词方法【1】是从一个包含足够多字符串或词元的初始集合开始,迭代地删除其中的…...
Dockerfile搭建ELK
使用 Dockerfile 安装 ELK 一、引言 ELK Stack(Elasticsearch, Logstash, Kibana)是一种流行的日志管理和分析解决方案。它允许用户实时搜索、分析和可视化日志数据。通过 Docker,可以方便地部署 ELK ,快速获取一个功能齐全的日…...
在合规的地方怎么用EACO地球链兑换交换价值?
地球链EACO(EarthChain,简称$E)是一种虚拟数字资产。 目前在中国大陆,虚拟资产相关业务活动属于金融活动,包括虚拟资产的交易、兑换等操作,因此应该谨慎去寻求如何用它来交换价值。 虚拟资产交易炒作活动&…...
VS无法安装Win10SDK_10.0.2200,快捷方法
Visual Studio无法安装Win10SDK_10.0.2200,我在安装VS2019、2022提示,软件就不能编译。 因为之前安装过VS软件,重新安装软件提示“无法安装”。 原因 之前安装在D盘,现在没有D盘了 说明 因为电脑第一次安装VS,会自动安…...
github多个账号配置多个SSH秘钥
背景 对于有多个github账号的同学,需要配置多个ssh秘钥分别管理多个账号。 方法 1、生成多个SSH秘钥 # 为第一个 GitHub 账号生成密钥 ssh-keygen -t ed25519 -C "your_email_1example.com" -f ~/.ssh/id_ed25519_github_work# 为第二个 GitHub 账号生…...
静态/动态代理详解,一次性看完再也不会搞不清!
代理官方原文翻译: 给其他对象提供一个代理或者占位符,来控制对这个对象的访问。 代理最核心的思想: 在客户端和目标对象之间创建一个“中介”,用于保护目标对象和增强目标对象 静态代理: 该代理对象需要我们手动…...
Webserver(2)GCC
目录 安装GCCVScode远程连接到虚拟机编写代码gcc编译过程gcc与g的区别Xftp连接虚拟机上传文件 安装GCC sudo apt install gcc g查看版本是7.5 touch test.c创建代码 但是在虚拟机中写代码很不方便 VScode远程连接到虚拟机编写代码 gcc test.c -o app在虚拟机中用gcc编译的…...
mac电脑设置chrome浏览器语言切换为日语英语等不生效问题
在chrome中设置了语言,并且已经置顶了,但是不生效,在windows上直接有设置当前语言为chrome显示语言,但是mac上没有。 解决办法 在系统里面有一个单独给chrome设置语言的: 单独给它设定成指定的语言,然后重…...
Python中的人工智能框架与实例
在人工智能(AI)领域,Python因其简洁的语法、丰富的库和强大的社区支持,成为了最受欢迎的编程语言之一。本文将详细介绍Python中的人工智能框架,并通过具体实例展示如何使用这些框架来实现不同的人工智能应用。 一、Python中的人工智能框架 …...
论文阅读(二十六):Dual Attention Network for Scene Segmentation
文章目录 1.Introduction3.DANet3.1Position Attention Module3.2Channel Attention Module 论文:Dual Attention Network for Scene Segmentation 论文链接:Dual Attention Network for Scene Segmentation 代码链接:Github 1.Intr…...
Stack和Queue(3)
Stack和Queue(3) priority_queue的模拟实现 priority_queue.h #include <vector>namespace soobin {template<class T, class Container vector<T>>class priority_queue{public://强制生成默认构造priority_queue() default;temp…...
怎样把学生的成绩单独告知家长?
期中考试季的到来让校园里的气氛似乎也变得紧张起来。家长们开始频繁地联系老师,希望了解孩子的表现;孩子们则在考试后,绞尽脑汁地想出各种理由,以期在成绩不理想时能减轻家长的失望。老师们更是忙得不可开交,不仅要批…...
vue3父组件控制子组件表单验证及获取子组件数值方法
1、关键部分的代码如下,我努力交代清楚了,希望能让大家看懂。 <template><KeepAlive><component ref"comp" :is"compNames[steps[compIndex].comp]" /></KeepAlive><el-button click"prevBtn"…...
【JavaEE】【多线程】单例模式
目录 一、设计模式1.1 单例模式1.1.1 饿汉模式1.1.2 懒汉模式 1.2 线程安全问题1.3 懒汉模式线程安全问题的解决方法1.3.1 原子性问题解决1.3.2 解决效率问题1.3.3 解决内存可见性问题和指令重排序问题 一、设计模式 在讲解案例前,先介绍一个概念设计模式ÿ…...
Java.6--多态-设计模式-抽象父类-抽象方法
一、多态 1.定义--什么是多态? a.同一个父类的不同子类对象,在做同一行为的时候,有不同的表现形式,这就是多态。(总结为:一个父类下的不同子类,同一行为,不同表现形式。࿰…...
JAVA Maven 的安装与配置
一、下载地址 官方网站:Maven – Download Apache Maven 我这里是3.8.6版本 二、安装步骤 maven安装之前要先安装jdk,请确保你的系统已经安装了jdk环境。 1.将下载好的 Maven 进行解压 apache-maven-3.6.8-bin.zip 2.配置本地仓库:修改 conf/settin…...
【程序分享】PCB元件坐标对齐工具 V1.3
↑↑↑点击上方蓝字,关注我们! “PCB元件坐标对齐工具 V1.3”脚本程序在PCB文档中将元件的坐标自动移动到参考圆弧的中心,参考圆弧支持机械层1层和禁止布线层,参考图元的位置任意,不局限于栅格位置。 程序会自动…...
[bug] vllm 0.6.1 RuntimeError: operator torchvision::nms does not exist
[bug] vllm 0.6.1 RuntimeError: operator torchvision::nms does not exist 环境 python 3.10 torch 2.4.0cu118 torchvision 0.19.0cu118 vllm 0.6.1.post2cu118问题详情 if torch._C._d…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
