Android开发MVP架构记录
Android开发MVP架构记录
安卓的MVP(Model-View-Presenter)架构是一种常见的软件设计模式,用于帮助开发者组织和分离应用程序的不同组成部分。MVP架构的目标是将应用程序的业务逻辑(Presenter)、用户界面(View)和数据模型(Model)解耦,从而提高代码的可维护性、可测试性和可扩展性。
下面是MVP架构中各个组成部分的角色和职责:
-
Model(模型):Model表示应用程序的数据模型层,负责处理数据的获取、存储、操作以及业务逻辑的处理。它可以是数据库、网络请求、文件系统等。Model不直接与View交互,而是通过Presenter进行通信。
-
View(视图):View是用户界面层,负责展示数据和接收用户的输入操作。它通常是Activity、Fragment或者自定义的View组件。View需要将用户的操作传递给Presenter,并将Presenter返回的数据展示给用户。
-
Presenter(展示器):Presenter是连接Model和View的桥梁,负责处理业务逻辑和控制数据流。它接收用户的操作请求并根据需要从Model中获取数据,然后将处理结果传递给View进行展示。Presenter不直接操作View,而是通过定义的接口进行交互。
MVP架构的优点包括:
- 分离关注点:MVP架构将业务逻辑、数据模型和用户界面分离,使得各自的责任更加清晰,易于维护和修改。
- 可测试性:由于Presenter和Model是独立的组件,并且没有直接依赖于Android Framework,因此可以更容易地进行单元测试。
- 可扩展性:通过定义接口和契约类(Contract)来规范组件之间的交互,可以方便地进行功能扩展和替换。
一个安卓项目结构示例:

-
activity:存放activity页面
-
adapter:存放适配器,配合RecycleView展示页面
-
base:存放基类,如:BaseActivity、BaseFargment,将一些公共方法写在基类中
-
entity:存放实体类,或一些数据结构对象
-
essential:存放接口类,里面的接口定义了一系列规范,是程序的核心
IView接口类:是(Activity或Fragment)视图的接口,定义视图有哪些执行方法,每个方法的具体实现中会对UI进行操作。
//所有IView的接口 public interface IView {//登录页接口规范interface LoginView extends BaseView{void successLogin();void failLogin();}//发现页接口规范interface ExploreView extends BaseView{void showBlogs(List<Blog> blogList);}//其他视图接口规范 }IPrensenter接口类:是Prensenter的接口,定义了Presenter的行为
//所有Presenter的接口 public interface IPresenter {//登录presenter接口interface login extends BasePresenter {void checkLogin(String body);}//发现prensenter接口interface exploreReq extends BasePresenter {void getPageBlogs(int page,int limit);}//其他presenter的接口 } -
fragment:存放fragment页面
-
presenter:存放prensenter实现类

public class ExplorePresenter implements IPresenter.exploreReq {IView.ExploreView exploreView;public ExplorePresenter(IView.ExploreView exploreView) {this.exploreView = exploreView;}@Overridepublic BaseView getBase() {return exploreView;}//观察者Observer<List<Blog>> blogObserver = new Observer<List<Blog>>() {@Overridepublic void onSubscribe(Disposable d) {}@Overridepublic void onNext(List<Blog> blogList) {exploreView.showBlogs(blogList);}@Overridepublic void onError(Throwable e) {}@Overridepublic void onComplete() {}};@Overridepublic void getPageBlogs(int page, int limit) {ApiServiceFactory.getInstance().getPageBlogs(page, limit).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(blogObserver);}} -
retrofit:网络请求框架,存放相关类。

ApiService类
//retrofit定义接口 public interface ApiService {@GET("api/getBlog/")Observable<List<Blog>> getPageBlogs(@Query("page") int page, @Query("limit") int limit);@POST("api/login")Observable<Result<User>> login(@Body String body);// 添加其他接口方法... }ApiServiceFactory
public class ApiServiceFactory {private static final String BASE_URL = "http://10.152.177.187:8180/";private static OkHttpClient okHttpClient;private static Retrofit retrofit;private static ApiService apiService;private static final long cacheSize = 1024 * 1024 * 15;// 缓存文件最大限制大小20Mprivate static String cacheDirectory = Environment.getExternalStorageDirectory() + "/aop"; // 设置缓存文件路径private static Cache cache = new Cache(new File(cacheDirectory), cacheSize); //public static ApiService getInstance() {if (apiService == null) {if (retrofit == null) {retrofit = createRetrofit();}apiService = retrofit.create(ApiService.class);}return apiService;}private static Retrofit createRetrofit() {return new Retrofit.Builder().baseUrl(BASE_URL).client(getOkHttpClient()).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();}private static OkHttpClient getOkHttpClient() {if (okHttpClient == null) {OkHttpClient.Builder builder = new OkHttpClient.Builder();builder.connectTimeout(30, TimeUnit.SECONDS); // 设置连接超时时间builder.writeTimeout(30, TimeUnit.SECONDS);// 设置写入超时时间builder.readTimeout(30, TimeUnit.SECONDS);// 设置读取数据超时时间builder.retryOnConnectionFailure(true);// 设置进行连接失败重试 // builder.addNetworkInterceptor(getInterceptor());if (Constants.ISDEBUG) {builder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));//拦截器}builder.cache(cache);// 设置缓存,cacheDir和cacheSize需要根据实际情况设置okHttpClient = builder.build();}return okHttpClient;}private static Interceptor getInterceptor() {// 返回你自定义的拦截器,如果没有特殊需求可以返回nullreturn null;} }Result类:规范返回数据结构类,使所有的返回数据结构为result类,真正数据存放在result.data中,这样就规范了返回结果。
//统一返回数据结构 public class Result<T> {private String code;private String msg;private T data; //T表示泛型public String getCode() {return code;}public String getMsg() {return msg;}public T getData() {return data;}public void setCode(String code) {this.code = code;}public void setMsg(String msg) {this.msg = msg;}public void setData(T data) {this.data = data;}public Result() {}public Result(T data) {this.data = data;}public static Result success() {Result result = new Result<>();result.setCode("200");result.setMsg("成功");return result;}public static <T> Result<T> success(T data) {Result<T> result = new Result<>(data);result.setCode("0");result.setMsg("成功");return result;}public static Result error(String code, String msg) {Result result = new Result();result.setCode(code);result.setMsg(msg);return result;} } -
util:存放工具类、常量类、全局变量
相关文章:
Android开发MVP架构记录
Android开发MVP架构记录 安卓的MVP(Model-View-Presenter)架构是一种常见的软件设计模式,用于帮助开发者组织和分离应用程序的不同组成部分。MVP架构的目标是将应用程序的业务逻辑(Presenter)、用户界面(V…...
day2作业
1,输入两个数,完成两个数的加减乘除 #输入两个数,完成两个数的加减乘除 num1int(input("请输入第一个数:")) num2int(input("请输入第二个数:")) print(str(num1)str(num2)str(num1num2)) print(str(num1)-str(num2)str…...
Python办公自动化之Word
Python操作Word 1、Python操作Word概述2、写入Word2.1、标题2.2、章节与段落2.3、字体与引用2.4、项目列表2.5、分页2.6、表格2.7、图片3、读取Word3.1、读取文档3.2、读取表格4、将Word表格保存到Excel5、格式转换5.1、Doc转Docx5.2、Word转PDF1、Python操作Word概述 python-d…...
力扣26:删除有序数组中的重复项
26. 删除有序数组中的重复项 - 力扣(LeetCode) 题目: 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 …...
基于C#的AE二次开发之IQueryFilter接口、ISpatialFilter接口、IQueryDef 接口的查询接口的介绍
一、开发环境 开发环境为ArcGIS Engine 10.2与Visual studio2010。在使用ArcEngine查询进行查询的时候主要使用三种查询接口IQueryFilter(属性查询) 、ISpatialFilter(空间查询) 、IQueryDef (多表查询) 那…...
Oracle 11g RAC部署笔记
搭了三次才搭好,要记录一下。 1. Oracle 11g RAC部署的相关步骤以及需要的包,可以参考这里。 Oracle 11g RAC部署_12006142的技术博客_51CTO博客Oracle 11g RAC部署,Oracle11gRAC部署操作环境:CentOS7.4Oracle11.2.0.4一、主机网…...
Redis 字符串操作实战(全)
目录 SET 存入键值对 SETNX SETEX SETBIT SETRANGE MSET 批量存入键值对 MSETNX PSETEX BITCOUNT 计算值中1的数量 BITOP 与或非异或操作 DECR 减1 DECRBY APPEND 追加 INCR 自增 INCRBY INCRBYFLOAT GET 取值 GETBIT GETRANGE GETSET 取旧值赋新值 MGET …...
python LeetCode 88 刷题记录
题目 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 注意:最终,合并…...
基于 Socket 网络编程
基于 Socket 网络编程 前言一、基于Socket的网络通信传输(传输层)二、UDP 的数据报套接字编程1、UDP 套接字编程 API2、使用 UDP Socket 实现简单通信 三、TCP 流套接字编程1、TCP 流套接字编程 API2、使用 TCP Socket 实现简单通信3、使用 Tcp 协议进行…...
关于C#.Net网页跳转的7种方法
一、目前在ASP.NET中页面传值共有这么几种方式:1.Response.Redirect("http://www.hao123.com",false); 目标页面和原页面可以在2个服务器上,可输入网址或相对路径。后面的bool值为是否停止执行当前页。 跳转向新的页面,原窗口被代…...
使用acme.sh申请免费ssl证书(Cloudflare方式API自动验证增加DNS Record到期证书到期自动重新申请)
下载acme.sh curl https://get.acme.sh | sh -s emailmyexample.comcd ~/.acme.sh/获取Cloudflare密钥 Preferences | Cloudflare 登录选择账户详情选择API Token选择创建令牌选择区域DNS模板,并设置编辑写入权限生成并复制令牌备用回到首页概览界面下部获取账号…...
【C语言】进阶——结构体+枚举+联合
①前言: 在之前【C语言】初阶——结构体 ,简单介绍了结构体。而C语言中结构体的内容还有更深层次的内容。 一.结构体 结构体(struct)是由一系列具有相同类型或不同类型的数据项构成的数据集合,这些数据项称为结构体的成员。 1.结构体的声明 …...
Socket编程基础(1)
目录 预备知识 socket通信的本质 认识TCP协议和UDP协议 网络字节序 socket编程流程 socket编程时常见的函数 服务端绑定 整数IP和字符串IP 客户端套接字的创建和绑定 预备知识 理解源IP和目的IP 源IP指的是发送数据包的主机的IP地址,目的IP指的是接收数据包…...
无线通信——Mesh自组网的由来
阴差阳错找到了一个工作,是做无线通信的,因为无线设备采用Mesh,还没怎么接触过,网上搜索下发现Mesh的使用场景不多,大部分都是用在家里路由器上面。所以写了片关于Mesh网的文档。Mesh网可应用在无网络区域的地方&#…...
LRU、LFU 内存淘汰算法的设计与实现
1、背景介绍 LRU、LFU都是内存管理淘汰算法,内存管理是计算机技术中重要的一环,也是多数操作系统中必备的模块。应用场景:假设 给定你一定内存空间,需要你维护一些缓存数据,LRU、LFU就是在内存已经满了的情况下&#…...
常用工具使用
ubuntu 1.1 ubuntu与windows 互相复制问题 方法一、 打开虚拟机 ,点击上方导航栏 ‘虚拟机’ 查看VMware Tools是否安装,安装即可 方法二、 apt-get autoremove open-vm-tools apt-get install open-vm-tools apt-get install open-vm-tools-desktop…...
HashMap源码解析_jdk1.8(一)
HashMap解析 HashMap源码解析_jdk1.8(一)哈希常用数据结构查找/插入/删除性能比较。哈希冲突 HashMap的数据结构HashMap相关变量size和capacity HashMap源码解析_jdk1.8(一) 哈希 Hash,一般翻译做“散列”࿰…...
Android最好用的日志打印库(自动追踪日志代码位置)
给大家推荐一个自己写的日志打印的库,我愿称之为最强日志打印库:BytUtilLog Byt是Big一统的缩写,大一统日志打印库,哈哈!搞个笑,很早就写好了,但后面忙起来就忘了写一篇文章推一下它了ÿ…...
面试官的哪些举动,暗示你通过了面试?
其实在求职过程中都会发现,求职者面试时间一般在20分钟以上,如果求职者较多,可能会在10分钟左右。(会在介绍以往工作上减少时间,内容主要以简单介绍,薪资要求,能力评价,到岗时间等等) 拿面试时…...
旅行季《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著想象和世界一样宽广
旅行季《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著想象和世界一样宽广...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...
