Android开发MVP架构记录

Android开发MVP架构记录

安卓的MVP(Model-View-Presenter)架构是一种常见的软件设计模式,用于帮助开发者组织和分离应用程序的不同组成部分。MVP架构的目标是将应用程序的业务逻辑(Presenter)、用户界面(View)和数据模型(Model)解耦,从而提高代码的可维护性、可测试性和可扩展性。

下面是MVP架构中各个组成部分的角色和职责:

  1. Model(模型):Model表示应用程序的数据模型层,负责处理数据的获取、存储、操作以及业务逻辑的处理。它可以是数据库、网络请求、文件系统等。Model不直接与View交互,而是通过Presenter进行通信。

  2. View(视图):View是用户界面层,负责展示数据和接收用户的输入操作。它通常是Activity、Fragment或者自定义的View组件。View需要将用户的操作传递给Presenter,并将Presenter返回的数据展示给用户。

  3. Presenter(展示器):Presenter是连接Model和View的桥梁,负责处理业务逻辑和控制数据流。它接收用户的操作请求并根据需要从Model中获取数据,然后将处理结果传递给View进行展示。Presenter不直接操作View,而是通过定义的接口进行交互。

MVP架构的优点包括:

  • 分离关注点:MVP架构将业务逻辑、数据模型和用户界面分离,使得各自的责任更加清晰,易于维护和修改。
  • 可测试性:由于Presenter和Model是独立的组件,并且没有直接依赖于Android Framework,因此可以更容易地进行单元测试。
  • 可扩展性:通过定义接口和契约类(Contract)来规范组件之间的交互,可以方便地进行功能扩展和替换。

一个安卓项目结构示例:

image-20230925185446075

  1. activity:存放activity页面

  2. adapter:存放适配器,配合RecycleView展示页面

  3. base:存放基类,如:BaseActivity、BaseFargment,将一些公共方法写在基类中

  4. entity:存放实体类,或一些数据结构对象

  5. 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的接口
    }
    
  6. fragment:存放fragment页面

  7. presenter:存放prensenter实现类

    image-20230925190614971

    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);}}
  8. retrofit:网络请求框架,存放相关类。

    image-20230925190803532

    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;}
    }
    
  9. util:存放工具类、常量类、全局变量

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

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

相关文章

Selenium自动化测试框架常见异常分析及解决方法

01 pycharm中导入selenium报错 现象: pycharm中输入from selenium import webdriver, selenium标红 原因1: pycharm使用的虚拟环境中没有安装selenium, 解决方法: 在pycharm中通过设置或terminal面板重新安装selenium 原因2: 当前项目下有selenium.py,和系统包名冲突导致, …

Linux学习第19天:Linux并发与竞争实例: 没有规矩不成方圆

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 先说点题外话&#xff0c;上周参加行业年会&#xff0c;停更了一周。接下来的周五就要开启国庆中秋双节模式&#xff0c;所以有的时候&#xff0c;尤其是工作以后…

JAVA学习-全网最详细

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

表格内日期比较计算

需求&#xff1a;在表格中新增数据&#xff0c;计算开始日期中最早的和结束日期中最晚的&#xff0c;回显到下方。 <el-formref"formRef":model"ruleForm":rules"rules"style"margin-top: 20px;"label-position"top">…

Golang 的 GMP:并发编程的艺术

前言 在 Golang 的并发编程中&#xff0c;GMP 是一个重要的概念&#xff0c;它代表了 Goroutine、M&#xff08;线程&#xff09;和 P&#xff08;调度器&#xff09;。这个强大的三位一体的并发模型使得 Golang 在处理并发任务时非常高效和灵活。通过 GMP 的组合&#xff0c;…

美轮美奂,尽在眼前——Aerial for Mac 高清鸟瞰屏保程序

想要让您的 Mac 屏幕焕发别样风采&#xff1f;那么&#xff0c;Aerial for Mac 高清鸟瞰屏保程序一定不容错过。这款应用程序将为您带来最优质的高清鸟瞰视频壁纸&#xff0c;让您的屏幕焕发无限活力和美感。 Aerial for Mac 高清鸟瞰屏保程序是一款专为 Mac 设计的屏幕保护程…

2023-9-25 货仓选址

题目链接&#xff1a;货仓选址 #include <iostream> #include <algorithm>using namespace std;const int N 100010;int n; int a[N];int main() {cin >> n;for(int i 0; i < n; i ) cin >> a[i];sort(a, a n);int res 0;for(int i 0; i < …

翻译像机翻?4点教会你ChatGPT高质量翻译

如果完全靠自己的英文和中文水平&#xff0c;要达到这样的翻译速度和质量那是不太可能的&#xff0c;主要还是得益于ChatGPT的帮助&#xff0c;首先用GPT-4的API粗翻&#xff0c;再用ChatGPT Plus精翻。很多人都用过ChatGPT翻译&#xff0c;但翻译出来的结果比起Google翻译和De…

C#通过重写Panel改变边框颜色与宽度的方法

在C#中,Panel控件是一个容器控件,用于在窗体或用户控件中创建一个可用于容纳其他控件的面板。Panel提供了一种将相关控件组合在一起并进行布局的方式。以下是Panel控件的详细使用方法: 在窗体上放置 Panel 控件: 在 Visual Studio 的窗体设计器中,从工具箱中拖动并放置一…

离散小波变换(概念与应用)

目录 概念光伏功率预测中,如何用离散小波变换提取高频特征概念 为您简单地绘制一些示意图来描述离散小波变换的基本概念。但请注意,这只是一个简化的示意图,可能不能完全捕捉到所有的细节和特性。 首先,我将为您绘制一个简单的小波函数和尺度函数的图像。然后,我会提供一…

链表oj题1(Leetcode)——移除链表元素,反转链表,链表的中间节点,

链表OJ 一&#xff0c;移除链表元素1.1分析1.2代码 二&#xff0c;找到链表的中间节点2.1分析2.2代码 三&#xff0c;反转链表3.1分析3.2代码 四&#xff0c;找到链表中倒数第k个节点4.1分析4.2代码 一&#xff0c;移除链表元素 移除链表元素 1.1分析 这里的删除要分成两种…

Android Jetpack组件架构 :LiveData的使用和原理

Android Jetpack组件架构&#xff1a; LiveDate的使用和原理 导言 继Lifecycle组件之后我们接下来要介绍的就是LiveDate组件&#xff0c;所谓LiveDate字面意思上就是有声明的数据&#xff0c;当数据有改动时该组件可以感知到这个操作并将该事件通知到其观察者&#xff0c;这样…

屏幕分辨率dpi解析(adb 调试查看)

authordaisy.skye的博客_CSDN博客-嵌入式,Qt,Linux领域博主 ro.sf.lcd_density属性指定了这个机型使用的dpi是多少&#xff0c;dpi全称是dots per inch&#xff0c;对角线每英寸的像素点的个数。 密度 ldpi mdpi hdpi xhdpi xxhdpi 分辨率 240x320 320x480 480x800 7…

2023-9-25 耍杂技的牛

题目链接&#xff1a;耍杂技的牛 #include <iostream> #include <algorithm>using namespace std;typedef pair<int, int> PII;const int N 50010;int n; PII cow[N];int main() {cin >> n;for(int i 0; i < n; i ){int w, s;cin >> w >…

Android 10.0 系统开启和关闭黑白模式主题功能实现

1. 概述 在10.0的rom系统开发定制化中,在系统SystemUI的下拉状态栏中,产品开发功能需求要求添加黑白模式功能开关的功能,就是打开黑白模式,系统颜色就会变成黑白颜色, 关闭黑白模式开关系统就会变成彩色模式,所以就需要了解下系统是怎么设置黑白模式和彩色模式的,然后添…

接口自动化测试之Mock

【软件测试面试突击班】如何逼自己一周刷完软件测试八股文教程&#xff0c;刷完面试就稳了&#xff0c;你也可以当高薪软件测试工程师&#xff08;自动化测试&#xff09; 1.Mock实现原理和实现机制 在某些时候&#xff0c;后端在开发接口的时候&#xff0c;处理逻辑非常复杂&a…

Android跨进程通信:Binder机制原理

目录 1. Binder到底是什么&#xff1f; 2. 知识储备 2.1 进程空间划分 2.2 进程隔离 & 跨进程通信&#xff08; IPC &#xff09; 2.3 内存映射 2.3.1 作用 2.3.2 实现过程 2.3.3 特点 2.3.4 应用场景 2.3.5 实例讲解 ① 文件读 / 写操作 ② 跨进程通信 3. Bi…

C#中的(++)和(--)运算符

目录 背景: 的前加 效果展示:​ 的后加 效果展示 :​ 总结: 背景: 自增和自减运算符存在于C/C/C#/Java等高级语言中&#xff0c;它的作用是在运算结束前(前置自增自减运算符 )或后(后置自增自减运算符 )将 变量的值加(或减)1。 在C#中&#xff0c;和--是自增和自减运…

基于springboot小区疫情防控系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

前端Vue3+element-plus表单输入框实现Cron表达式校验

页面如下&#xff1a; 本来想手写正则表达式校验&#xff0c;结果发现很麻烦&#xff0c;cron表达式组成如下&#xff1a; 开发使用框架为vue3element-plus&#xff0c;于是选择cron-validator依赖。使用步骤如下&#xff1a; 1、通过npm install cron-validator命令安装&…