【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架构优点

  1. View层与Model层完全分离

  2. 所有View层 和 Model层 逻辑交互都在Presenter

  3. 后续扩展性/可维护性强,M层(负责数据业务模型), P层(负责M层与V层的交互逻辑)

  4. 定位修改Bug方便:

    如果是修改界面交互相关的,直接找V层修改

    如果是修改数据业务逻辑,直接找M层修改

image-20241018141154575

MVP架构特点

关系:

  1. View收到用户的操作

  2. View把用户的操作,交给Presenter

  3. Presenter直接操作Model进行业务逻辑处理

  4. Model处理完毕后,通知Presenter

  5. Presneter收到通知后,在去更新View

方式:

是双向的通信方式

优点:

  1. View层与Model层完全分离
  2. 所有的逻辑交互都在Presenter
  3. MVP分层较为严谨

image-20241018141452545

image-20241018165112763

示例

  1. Model (数据层)

Model 负责处理数据逻辑,判断用户名和密码是否正确。

public class LoginModel {// 模拟用户登录数据public boolean validateUser(String username, String password) {// 简单模拟,假设用户名为"user",密码为"password"时登录成功return username.equals("user") && password.equals("password");}
}
  1. 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();}
}
  1. 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();}}
}
  1. 布局文件 (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>

工作流程:

  1. 用户在 LoginActivity 中输入用户名和密码并点击登录按钮。
  2. LoginActivity 作为 View 层,将用户输入传递给 LoginPresenter
  3. LoginPresenter 从 View 获取用户名和密码,并调用 LoginModel 来验证用户输入。
  4. LoginModel 验证输入是否正确,然后将结果返回给 LoginPresenter
  5. LoginPresenter 根据验证结果通知 LoginActivity 更新UI,显示登录成功或失败的消息。

已经到底啦!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/883308.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于自适应VSG控制的光伏混合储能构网型逆变系统MATLAB仿真模型

模型简介 此模型源侧部分采用光伏发电系统与混合储能系统&#xff08;蓄电池超级电容&#xff09;&#xff0c;并网逆变器采用虚拟同步发电机&#xff08;VSG&#xff09;控制&#xff0c;为系统提供惯量阻尼支撑。同时对VSG控制部分进行了改进&#xff0c;采用构造函数法对虚…

论文阅读(二十九):Multi-scale Interactive Network for Salient Object Detection

文章目录 Abstract1.Introduction2.Scale VariationProposed Method3.1Network Overview3.2Aggregate Interaction Module3.3 Self-Interaction Module3.4Consistency-Enhanced Loss 4.Experiments4.1Implementation Details4.2 Comparison with State-of-the-arts4.3Ablation …

【力扣】[Java版] 刷题笔记-21. 合并两个有序链表

题目&#xff1a; 21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 解题思路 从题目和示例可以看出&#xff0c;应该是要循环遍历链表进行比较&#xff0c;然后组成新的链表。 第一种&#xff1a;递归…

存储过程(SQL)

1.存储过程 存储过程&#xff08;Stored Procedure&#xff09;是一组为了完成特定功能的SQL语句集&#xff0c;经编译后存储在数据库中&#xff0c;用户通过指定存储过程的名字并给定参数&#xff08;如果该存储过程带有参数&#xff09;来调用执行它。 2.MySQL存储过程创建…

PostgreSQL的前世今生

PostgreSQL的起源可以追溯到1977年的加州大学伯克利分校&#xff08;UC Berkeley&#xff09;的Ingres项目。该项目由著名的数据库科学家Michael Stonebraker领导&#xff0c;他是2015年图灵奖的获得者。以下是PostgreSQL起源的详细概述&#xff1a; 一、早期发展 Ingres项目…

LabVIEW换流变换器智能巡检系统

基于LabVIEW的换流变换器智能巡检系统通过自动化检测和数据分析&#xff0c;提高换流变换器的运行效率和可靠性&#xff0c;降低人工维护成本。 项目背景&#xff1a; 换流变压器作为电力系统的重要组成部分&#xff0c;其性能的可靠性直接影响到整个电网的稳定运行。然而&…

完美解决phpstudy安装后mysql无法启动

phpstudy数据库无法启动有以下几个原因。 一、自己在电脑上安装了MySQL数据库,MySQL的服务名为MySQL,这会与phpstudy的数据库的服务名发生冲突&#xff0c;从而造成phpstudy中的数据库无法启动&#xff0c;这时我们只需要将自己安装的MySQL的服务名改掉就行。 但是&#xff0…

软件测试的重要一环:「性能测试」怎么做?

性能测试是软件测试中的重要一环&#xff0c;今天给大家介绍性能测试及如何使用RunnerGo完成性能测试任务。 性能测试是什么&#xff1f; 一句话概括&#xff1a;不断地通过不同场景的系统表现去探究系统设计与资源消耗之间的平衡&#xff0c;为开发人员提供消除瓶颈所需的诊…

Ajax:表单 模板引擎

Ajax&#xff1a;表单 & 模板引擎 form 表单form 属性 Ajax操控表单事件监听阻止默认行为收集表单数据 模板引擎art-template{{}}语法原文输出条件输出循环输出过滤器 原理 form 表单 在HTML中&#xff0c;可以通过<form>创建一个表单&#xff0c;收集用户信息。而采…

基于docker 部署redis

1、拉取镜像 docker pull redis:latest如果拉取失败可以尝试下配置镜像源&#xff0c;具体参考如下&#xff0c;目前暂可以使用 Docker切换镜像源-CSDN博客 2、创建配置文件 mkdir /usr/local/redis/conf vim redis.conf bind 0.0.0.0#protected-mode no port 6379 tcp-b…

Fast Simulation of Mass-Spring Systems in Rust 论文阅读

参考资料&#xff1a; Fast Simulation of Mass-Spring Systems in Rust 论文阅读&#xff1a;Fast Simulation of Mass-Spring Systems 【论文精读】讲解刘天添2013年的fast simulation of mass spring system(Projective Dynamics最早的论文) Projective Dynamics笔记(一…

面试经典 150 题 第三周代码

【题目链接】 80. 删除有序数组中的重复项 II 【参考代码】 双指针 class Solution { public:int removeDuplicates(vector<int>& nums) {int size nums.size();if(size < 2){return size;}int slow 2, fast 2;while(fast < size){if(nums[slow-2] ! num…

【C++数学 负进制】1017. 负二进制转换|1697

本文涉及知识点 数学 LeetCode1017. 负二进制转换 给你一个整数 n &#xff0c;以二进制字符串的形式返回该整数的 负二进制&#xff08;base -2&#xff09;表示。 注意&#xff0c;除非字符串就是 “0”&#xff0c;否则返回的字符串中不能含有前导零。 示例 1&#xff1a…

可训练的YOLO距离检测

由于很多场景需要测距&#xff0c;而深度图、点云等获取、配准、融合困难&#xff0c;尝试直接在目标增加距离标注进行训练&#xff0c;理论上标注准确&#xff0c;数据集够&#xff0c;就可以实现。 目前已经跑通YOLO增加距离训练&#xff1a; 目前准度不够&#xff0c;仅将…

Flutter Image和Text图文组件实战案例

In this section, we’ll go through the process of building a user interface that showcases a product using the Text and Image widgets. We’ll follow Flutter’s best practices to ensure a clean and effective UI structure. 在本节中&#xff0c;我们将使用“Te…

JVM 实战篇(一万字)

此笔记来至于 黑马程序员 内存调优 内存溢出和内存泄漏 内存泄漏&#xff08;memory leak&#xff09;&#xff1a;在Java中如果不再使用一个对象&#xff0c;但是该对象依然在 GC ROOT 的引用链上&#xff0c;这个对象就不会被垃圾回收器回收&#xff0c;这种情况就称之为内…

鸿蒙next之导航组件跳转携带参数

官方文档推荐使用导航组件的形式进行页面管理&#xff0c;官方文档看了半天也没搞明白&#xff0c;查了各种文档才弄清楚。以下是具体实现方法&#xff1a; 在src/main/resources/base/profile下新建router_map.json文件 里边存放的是导航组件 {"routerMap" : [{&q…

从汇编角度看C/C++函数指针与函数的调用差异

函数指针本质上是一个指针变量&#xff0c;只不过这个变量保存的地址是一个函数的地址&#xff0c;那么直接调用函数和通过函数指针调用有没有区别呢&#xff1f;答案是有的&#xff0c;下面的代码是一个直接调用函数和通过指针调用函数的例子&#xff0c;使用gdb反汇编main函数…

vue开发的时候,目录名、文件名、函数名、变量名、数据库字段等命名规范

在Vue开发中&#xff0c;函数名、文件名、目录名、变量名、数据库字段名的命名规范各有其特点&#xff0c;以下是根据Vue及JavaScript的命名习惯进行的详细解答&#xff1a; 分析 目录名 通常使用kebab-case&#xff08;短横线命名法&#xff09;&#xff0c;全部小写&#x…

mac电脑设置chrome浏览器语言切换为日语英语等不生效问题

在chrome中设置了语言&#xff0c;并且已经置顶了&#xff0c;但是不生效&#xff0c;在windows上直接有设置当前语言为chrome显示语言&#xff0c;但是mac上没有。 解决办法 在系统里面有一个单独给chrome设置语言的&#xff1a; 单独给它设定成指定的语言&#xff0c;然后重…