MVC,MVP,MVVM的理解和区别
MVC
MVC ,早期的开发架构,在安卓里,用res代表V,activity代表Controller层,Model层完成数据请求,更新操作,activity完成view的绑定,以及业务逻辑的编写,更新view,这种模式是单向的,虽然代码存在分层,但是之间的耦合性还是很高,并且C层做的事情很多,久而久之会变得臃肿。

代码实现:
ViewModel
static class StudentModel{private String name;private int age;public StudentModel(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
View层
static class StudentView{public void PrintStudentData(String name ,int age){System.out.println("Student name:"+name+" age:"+age);}}
Controller
static class StudentController{StudentModel model;StudentView view;public StudentController(StudentModel model, StudentView view) {this.model = model;this.view = view;}public void setStudentName(String name){model.setName(name);}public String getStudentName(){return model.getName();}public void setStudentAge(int age){model.setAge(age);}public Integer getStudentAge(){return model.getAge();}public void updateView(StudentView view){view.PrintStudentData(model.getName(),model.getAge());}}
完整代码
package com.example.lib;public class MvcTest {public static void main(String[] args) {StudentModel student = getStudentDataBase();StudentView view = new StudentView();StudentController controller = new StudentController(student,view);controller.updateView(view);controller.setStudentName("lisi");controller.updateView(view);}public static StudentModel getStudentDataBase(){return new StudentModel("zhangsan",18);}static class StudentModel{private String name;private int age;public StudentModel(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}static class StudentView{public void PrintStudentData(String name ,int age){System.out.println("Student name:"+name+" age:"+age);}}static class StudentController{StudentModel model;StudentView view;public StudentController(StudentModel model, StudentView view) {this.model = model;this.view = view;}public void setStudentName(String name){model.setName(name);}public String getStudentName(){return model.getName();}public void setStudentAge(int age){model.setAge(age);}public Integer getStudentAge(){return model.getAge();}public void updateView(StudentView view){view.PrintStudentData(model.getName(),model.getAge());}}}

MVP
于是,出现了MVP模式,这个架构模式在安卓移动端开发中比较常见,将Activity和res统一作为V层,Model层还是完成数据的请求和更新,新建了一个类Presenter,用来作为P层,这样的好处是,方便管理每一个Activity的业务逻辑,拿到数据后,通过接口回调的方式,更新View层,实现了双向通信。缺点是需要实现Presenter类,并且需要开发接口,对简单的业务逻辑比较繁琐,且P层的事情还是比较臃肿

代码实现(以登录事务为例):
ViewModel层
相比与MVC的ViewModel,MVP的不同在于ViewModle多实现了一个IUser接口,从而实现双向通信
interface IUser{void login(String name,String password,OnLoginListener listener);}interface OnLoginListener{void loginFail();void loginSuccess(User user);}static class UserModel implements IUser{@Overridepublic void login(String name, String password, OnLoginListener listener) {//模拟一下登录if(name.equals("admin")&&password.equals("123456")){User user = new User();user.setUsername(name);user.setPassword(password);listener.loginSuccess(user);}else{listener.loginFail();}}}
View层:
在Android开发中,MVP架构模式里,View层指的是Activity和res。同理,也实现了一个IUserLogin接口,从而和P层实现双向通信
static class UserView implements IUserLogin{@Overridepublic void showLoading() {System.out.println("正在登录...");}@Overridepublic void hideLoading() {System.out.println("登录完成,获取结果");}@Overridepublic void loginFail() {System.out.println("登录失败");}@Overridepublic void loginSuccess(User user) {System.out.println("username:"+ user.getUsername()+" 登陆成功");}}interface IUserLogin{void showLoading();void hideLoading();void loginFail();void loginSuccess(User user);}
Presenter层
static class UserPresenter {private final UserModel userModel;private final UserView userView;private final User user;public UserPresenter(UserView userView) {this.userModel = new UserModel();this.userView = userView;user = new User("admin","123456");}void login(){userView.showLoading();userModel.login(user.getUsername(), user.getPassword(), new OnLoginListener() {@Overridepublic void loginFail() {userView.hideLoading();userView.loginFail();}@Overridepublic void loginSuccess(User user) {userView.hideLoading();userView.loginSuccess(user);}});}}
完整代码如下:
package com.example.lib;public class MvpTest {public static void main(String[] args) {UserView loginView = new UserView();UserPresenter presenter = new UserPresenter(loginView);presenter.login();}static class User{String username;String password;public User() {}public User(String username, String password) {this.username = username;this.password = password;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}interface IUser{void login(String name,String password,OnLoginListener listener);}interface OnLoginListener{void loginFail();void loginSuccess(User user);}static class UserModel implements IUser{@Overridepublic void login(String name, String password, OnLoginListener listener) {//模拟一下登录if(name.equals("admin")&&password.equals("123456")){User user = new User();user.setUsername(name);user.setPassword(password);listener.loginSuccess(user);}else{listener.loginFail();}}}static class UserView implements IUserLogin{@Overridepublic void showLoading() {System.out.println("正在登录...");}@Overridepublic void hideLoading() {System.out.println("登录完成,获取结果");}@Overridepublic void loginFail() {System.out.println("登录失败");}@Overridepublic void loginSuccess(User user) {System.out.println("username:"+ user.getUsername()+" 登陆成功");}}interface IUserLogin{void showLoading();void hideLoading();void loginFail();void loginSuccess(User user);}static class UserPresenter {private final UserModel userModel;private final UserView userView;private final User user;public UserPresenter(UserView userView) {this.userModel = new UserModel();this.userView = userView;user = new User("admin","123456");}void login(){userView.showLoading();userModel.login(user.getUsername(), user.getPassword(), new OnLoginListener() {@Overridepublic void loginFail() {userView.hideLoading();userView.loginFail();}@Overridepublic void loginSuccess(User user) {userView.hideLoading();userView.loginSuccess(user);}});}}}

MVVM
再后面,就是MVVM,同理,Activity和res还是作为V层,Model层请求数据和更新,出现了一个ViewModel的层,这个类的职责在于,对数据进行绑定,以数据驱动View层,同样,当视图层改变后,Model层也能更新,从而实现了M和V之间的双向绑定。最常用的是谷歌2015年推出的jetpack的组件DataBinding,无须进行view绑定,避免了空指针等很多繁琐的业务逻辑。
代码实现:略,用JetPack提供的databinding即可
总结
MVC,MVP,MVVM的出现,都是为了视图分层,使代码结构,逻辑变得清晰,同时,实现类的单一职责,降低耦合度。但是同时选用架构设计模式的时候,也要根据业务类型来考虑,避免出现大多繁琐的设计,总之,一切为了开发效率。
相关文章:
MVC,MVP,MVVM的理解和区别
MVC MVC ,早期的开发架构,在安卓里,用res代表V,activity代表Controller层,Model层完成数据请求,更新操作,activity完成view的绑定,以及业务逻辑的编写,更新view…...
【TypeScript】一直提示 :无法重新声明块范围变量
【TypeScript】一直提示 :无法重新声明块范围变量 问题描述:在VSCode中编写ts代码时,编写保存完之后,通过tsc 文件名.ts编译就会看到变量名下面出现了红色的波浪线,提示的内容是无法重新声明块范围变量。 解决方法&am…...
【python自动化】七月PytestAutoApi开源框架学习笔记(一)
前言 本篇内容为学习七月大佬开源框架PytestAutoApi记录的相关知识点,供大家学习探讨 项目地址:https://gitee.com/yu_xiao_qi/pytest-auto-api2 阅读本文前,请先对该框架有一个整体学习,请认真阅读作者的README.md文件。 本文…...
Python学习 -- logging模块
logging 模块是 Python 中用于记录日志的标准库,它提供了丰富的功能,可以帮助开发者进行日志记录和管理。以下是关于logging模块的详细使用方式,包括日志级别、处理流程、Logger 类、Handler 类、Filter 类、Formatter 类以及模块中常用函数等…...
【socket】getaddrinfo、getsockname、getpeername对比
这三个函数都是在网络编程中用来获取地址信息的,但是它们的使用场景和功能有所不同。getaddrinfo(): 这个函数主要用于将一个主机名(或者 IP 地址)和端口号转换成适用于 socket() 函数的一个或多个套接字地址结构。它能够处理 IPv4 和 IPv6 地…...
【MySQL】表的增删改查(进阶)
表的增删改查(进阶) 一. 数据库约束1. 约束类型2. NULL约束3. UNIQUE:唯一约束4. DEFAULT:默认值约束5. PRIMARY KEY:主键约束6. FOREIGN KEY:外键约束7. CHECK约束 二. 表的设计1. 一对一2. 一对多3. 多对…...
关于安卓13中Android/data目录下的文件夹只能查看无法进行删改的问题
前言 因为升级了安卓13,然后有个app需要恢复数据,打算和以前一样直接删除Android/data下对应目录再添加,结果不行,以下是结合网上以及自己手机情况来做的一种解决方案。 解决 准备: 待恢复app(包名com.…...
Vulnhub: Masashi: 1靶机
kali:192.168.111.111 靶机:192.168.111.236 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.236查看80端口的robots.txt提示三个文件 snmpwalk.txt内容,tftp服务在1337端口 sshfolder.txt内容,…...
校园二手物品交易系统微信小程序设计
系统简介 本网最大的特点就功能全面,结构简单,角色功能明确。其不同角色实现以下基本功能。 服务端 后台首页:可以直接跳转到后台首页。 用户信息管理:管理所有申请通过的用户。 商品信息管理:管理校园二手物品中…...
Pixillion Pro for Mac:将您的图像转换为艺术佳作
Pixillion for Mac有着非常强大的图像转换功能和简单的使用方法,帮助你快速完成大批量图像转换的工作,支持一键转换jpeg、jpg、bmp、png、gif、raf、heic等各种格式的图像文件,同时pixillion mac激活版还提供了图像旋转、添加水印、调整图像大…...
【上海迪士尼度假区】技术解决方案
开源平台地址Giteehttps://gitee.com/issavior/disney 技术解决方案 1. 背景2. 技术架构3. 业务架构3.1 架构图3.2 说明 4. 技术能力4.1 自研中间件4.2 定制化中间件 5. 领域模型6. 数据模型7. 交易链路8. 状态机8. 接口文档 1. 背景 上海迪士尼度假区已运营近10年,…...
每日刷题-2
目录 一、选择题 二、编程题 1、倒置字符串 2、排序子序列 3、字符串中找出连续最长的数字串 4、数组中出现次数超过一半的数字 一、选择题 1、 题目解析: 二维数组初始化的一般形式是: 数据类型 数组名[常量表达式1][常量表达式2] {初始化数据}; 其…...
AOSP内置搜狗输入并设置默认输入法
前期准备 AOSP分支:aosp13_r7 系统版本:Ubuntu 22.04.1 LTS 工具:手,vscode,winscp(因为我是用的服务器编译) 下载搜狗输入法 思路: 1.集成搜狗输入法到aosp 2.删除系统输入法 3.设置搜狗输入法为默…...
ICCV 2023|通过慢学习和分类器对齐在预训练模型上进行持续学习
点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 作者介绍 张耕维 悉尼科技大学在读博士生,研究方向为持续学习 报告题目 通过慢学习和分类器对齐在预训练模型上进行持续学习 内容简介 持续学习研究的目标在于提高模型利用顺序到达的数据进行学习的…...
蓝桥杯打卡Day5
文章目录 日志排序重复者 一、日志排序IO链接 本题思路:本题就是根据就是排序的知识点,在sort内部可以使用仿函数来改变此时排序规则。 #include <bits/stdc.h>const int N10010; int n; std::string logs[N];int main() {std::ios::sync_with_stdio(false)…...
QT for andriod
QT for andriod 开发 apk软件,因为一些特殊的原因,在这里简单的记录一哈自己开发apk的流程和心得。 首先说明我采用的环境有哪些? 1、QT的版本,个人建议5.15.2的版本及以上,我是用的5.15.2。 2、andriod studio 可以…...
【广州华锐互动】AR技术在配电系统运维中的应用
随着科技的不断发展,AR(增强现实)技术逐渐走进了我们的生活。在电力行业,AR技术的应用也为巡检工作带来了许多新突破,提高了巡检效率和安全性。本文将从以下几个方面探讨AR配电系统运维系统的新突破。 首先,AR技术可以实现虚拟巡检…...
TiDB 一栈式综合交易查询解决方案获“金鼎奖”优秀金融科技解决方案奖
日前,2023“金鼎奖”评选结果揭晓, 平凯星辰(北京)科技有限公司研发的 TiDB 一栈式综合交易查询解决方案获“金鼎奖”优秀金融科技解决方案奖 , 该方案已成功运用于 多家国有大行、城商行和头部保险企业 。 此次获奖再…...
《网络是怎样连接的》(六)
本文主要取材于 《网络是怎样连接的》 第六章。 目录 6.1 服务器概览 6.2 服务器的接收操作 6.3 Web服务器程序解释请求消息并作出响应 6.4 浏览器接收响应消息并显示内容 简述:本文主要内容是解释 网络包到达服务器之后,如何给客户端响应的。 服务…...
2023年高教社杯数学建模国赛 赛题浅析
2023年国赛如期而至,为了方便大家尽快确定选题,这里将对赛题进行浅析,以分析赛题的主要难点、出题思路以及选择之后可能遇到的难点进行说明,方便大家尽快确定选题。 难度排序 B>A>C 选题人数 C>A>B (预估结果&…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
