Android开发MVP架构记录

news2024/12/23 19:05:50

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;
        }
    
        @Override
        public BaseView getBase() {
            return exploreView;
        }
    
        //观察者
        Observer<List<Blog>> blogObserver = new Observer<List<Blog>>() {
            @Override
            public void onSubscribe(Disposable d) {
    
            }
    
            @Override
            public void onNext(List<Blog> blogList) {
                exploreView.showBlogs(blogList);
            }
    
            @Override
            public void onError(Throwable e) {
    
            }
    
            @Override
            public void onComplete() {
    
            }
        };
    
        @Override
        public 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;// 缓存文件最大限制大小20M
        private 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() {
            // 返回你自定义的拦截器,如果没有特殊需求可以返回null
            return 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.coloradmin.cn/o/1040411.html

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

相关文章

由于找不到msvcr110.dll的5种解决方法

在使用电脑的过程中&#xff0c;我们可能会遇到一些问题&#xff0c;比如打开软件时提示找不到 msvcr110.dll 文件丢失。这通常意味着该文件已被删除或损坏&#xff0c;导致程序无法正常运行。本文将介绍几种解决方案&#xff0c;帮助您解决这个问题。 首先&#xff0c;我们需…

Linxu下c语言实现socket+openssl数据传输加密

文章目录 1. Socket连接建立流程2、SocketSSL的初始化流程3、初始化SSL环境&#xff0c;证书和密钥4、SocketSSL 的c语言实现4.1 编写SSL连接函数4.2 编写加密服务端server.c4.3 编写加密客户端client.c 5、使用tcpdump检验源码获取 在进行网络编程的时候&#xff0c;我们通常使…

分布式算法相关,使用Redis落地解决1-2亿条数据缓存

面试题&#xff1a;1~2亿数据需要缓存&#xff0c;请问如何设计个存储案例 回答&#xff1a;单机单台100%不可能&#xff0c;肯定是分布式存储&#xff0c;用redis如何落地&#xff1f; 一般业界有三种解决方案&#xff1a; 哈希取余分区 2亿条记录就是2亿个k&#xff0c;v&…

Linux学习-HIS部署(3)

Jenkins插件资源下载 Jenkins部署 Jenkins部署 #Jenkins主机安装OpenJDK环境 [rootJenkins ~]# yum clean all; yum repolist -v ... Total packages: 8,265 [rootJenkins ~]# yum -y install java-11-openjdk-devel.x86_64 #安装OpenJDK11 [rootJenkins ~]# ln -s /usr/l…

Css 美化滚动条

/*设置滚动条宽度为 6px*/ ::-webkit-scrollbar {width: 6px; } /*设置背景颜色&#xff0c;并设置边框倒角&#xff0c;设置滚动动画&#xff0c;0.2 */ ::-webkit-scrollbar-thumb {background-color: #0003;border-radius: 10px;transition: all .2s ease-in-out; } /*设置滚…

探索创意的新辅助,AI与作家的完美合作

在现代社会&#xff0c;文学创作一直是人类精神活动中的重要一环。从古典文学到现代小说&#xff0c;从诗歌到戏剧&#xff0c;作家们以他们的独特视角和文学天赋为我们展示了丰富多彩的人生世界。而近年来&#xff0c;人工智能技术的快速发展已经渗透到各行各业&#xff0c;文…

Leetcode191. 位1的个数

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回其二进制表达式中数字位数为 1 的个数&#xff08;也被称为汉明重量&#xff09;。 思路&…

人工智能AI 全栈体系(六)

第一章 神经网络是如何实现的 这些年神经网络的发展越来越复杂&#xff0c;应用领域越来越广&#xff0c;性能也越来越好&#xff0c;但是训练方法还是依靠 BP 算法。也有一些对 BP 算法的改进算法&#xff0c;但是大体思路基本是一样的&#xff0c;只是对 BP 算法个别地方的一…

mapper文件添加@Mapper注解爆红

如图所示 报错原因&#xff1a;缺少相关的依赖 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version> </dependency> 添加之后并刷新依赖…

C++: stack 与 queue

目录 1.stack与queue stack queue 2.priority_queue 2.1相关介绍 2.2模拟实现priority_queue --仿函数: --push --pop --top --size --empty --迭代器区间构造 2.3仿函数 3.容器适配器 stack模拟实现 queue模拟实现 学习目标: 1.stack和queue介绍与使用 2.pri…

Toaster - Android 吐司框架,专治 Toast 各种疑难杂症

官网 https://github.com/getActivity/Toaster 这可能是性能优、使用简单&#xff0c;支持自定义&#xff0c;不需要通知栏权限的吐司 想了解实现原理的可以点击此链接查看&#xff1a;Toaster 源码 集成步骤 如果你的项目 Gradle 配置是在 7.0 以下&#xff0c;需要在 bui…

如何使用Docker安装最新版本的Redis并设置远程访问(含免费可视化工具)

文章目录 安装Docker安装Redisredis.conf文件远程访问Redis免费可视化工具相关链接Docker是一种开源的应用容器引擎,使用Docker可以让我们快速部署应用环境,本文介绍如何使用Docker安装最新版本的Redis。 安装Docker 首先需要安装Docker,具体的安装方法可以参考Docker官方文…

用友U8 crm客户关系管理存在任意文件上传漏洞2 附POC

文章目录 用友U8 crm客户关系管理存在任意文件上传漏洞2 附POC1. 用友U8 crm客户关系管理简介2.漏洞描述3.影响版本4.fofa查询语句5.漏洞复现6.POC&EXP7.整改意见8.往期回顾 用友U8 crm客户关系管理存在任意文件上传漏洞2 附POC 免责声明&#xff1a;请勿利用文章内的相关…

知识图谱(5)知识表示

基于Node2Vec补全KG 知识图谱属于异质图&#xff0c;图谱包含三个元素&#xff1a;实体&#xff08;图中的节点&#xff09;&#xff0c;类型&#xff08;节点的标识&#xff09;&#xff0c;关系&#xff08;边的标识&#xff09;。KG就是把所有不同种类的信息连接在一起而得…

第1篇 目标检测概述 —(2)目标检测算法介绍

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。目标检测算法是一种计算机视觉算法&#xff0c;用于在图像或视频中识别和定位特定的目标物体。常见的目标检测算法包括传统的基于特征的方法&#xff08;如Haar特征和HOG特征&#xff09;以及基于深度学习的方法&#xff0…

C语言指针笔试题讲解

大家好&#xff0c;我们来学习一些C语言的指针笔试题。对于C语言指针的模块想必大家都非常的头疼吧&#xff0c;那么我们就来就来看看一些关于C语言指针的笔试题。 首先让我们看到我们今天的第一题。 int main() { int a[5] { 1, 2, 3, 4, 5 }; int *ptr (int *)(&a 1)…

AUTOSAR RTE介绍(更新版230925)

RTE是什么 AUTOSAR RTE(Run Time Environment)实现了AUTOSAR系统中的虚拟功能总线(VFB),提供了SWC(Software Component)之间的访问接口和SWC对于BSW资源的访问接口。RTE为SWC中的Runnable提供与其他SWC或者BSW模块通信的接口,RTE将Runnable映射到OS Task中,并且管理Runna…

二进制中1的个数 C++实现

题目&#xff1a; 代码&#xff1a; #include<iostream> using namespace std; const int N100010; int a[N]; int n;int lowbit(int x){return x & -x; }int main(){scanf("%d",&n);for(int i0;i<n;i) scanf("%d",&a[i]);for(int i…

抽检监测实施

声明 本文是学习GB-T 42893-2023 电子商务交易产品质量监测实施指南. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件提供了开展电子商务交易的有形产品质量监测的总则&#xff0c;监测准备、监测实施、监测效果评价 与反馈等过程指导…

this.$nextTick()的使用场景

事件循环机制&#xff1a; 同步代码执行->查找异步队列&#xff0c;推入执行栈&#xff0c;执行Vue.nextTick[事件循环1]->查找异步队列&#xff0c;推入执行栈&#xff0c;执行Vue.nextTick[事件循环2]->查找异步队列&#xff0c;推入执行栈&#xff0c;执行Vue.nex…