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分钟左右。(会在介绍以往工作上减少时间,内容主要以简单介绍,薪资要求,能力评价,到岗时间等等) 拿面试时…...

旅行季《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著想象和世界一样宽广
旅行季《乡村振兴战略下传统村落文化旅游设计》许少辉八一新著想象和世界一样宽广...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...