Android Retrofit + RxJava + OkHttp 网络请求高效封装方案

Retrofit + RxJava + OkHttp 是 Android 开发中常用的网络请求库组合。Retrofit 是一个类型安全的 HTTP 客户端,RxJava 是一个响应式编程库,OkHttp 是一个高效的 HTTP 客户端。

Retrofit + RxJava + OkHttp 的组合可以提供以下功能:
职责清晰

RetrofitClient 负责 Retrofit 和 OkHttp 的初始化。
ApiServiceHelper 负责动态创建 API 服务实例。
NetworkHelper 负责发起网络请求和处理结果

1. 动态配置 Retrofit 和 OkHttp
允许在运行时动态修改 Retrofit 和 OkHttp 的配置,例如 Base URL、超时时间、拦截器等。

  1. 统一错误处理
    增强错误处理的灵活性,支持自定义错误处理器。

  2. 支持多环境切换
    通过配置文件或 Build Variants 动态切换测试环境和生产环境。

  3. 添加缓存机制
    通过 OkHttp 的缓存拦截器实现本地缓存,减少网络请求。

  4. Token 自动管理
    通过拦截器自动添加 Token 并处理 Token 过期。

  5. 支持文件上传/下载
    扩展 API 服务接口,支持文件操作。

  6. 日志优化
    根据不同的 Build 类型(Debug/Release)动态调整日志级别。

  7. 生命周期绑定
    将网络请求与 Activity/Fragment 的生命周期绑定,避免内存泄漏。

代码如下:
RetrofitClient:支持动态配置

import okhttp3.Cache;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import java.io.File;
import java.util.concurrent.TimeUnit;

public class RetrofitClient {
    private static Retrofit retrofit;
    private static OkHttpClient okHttpClient;

    private RetrofitClient() {
        // 私有构造函数,防止外部实例化
    }

    public static Retrofit getRetrofit() {
        if (retrofit == null) {
            synchronized (RetrofitClient.class) {
                if (retrofit == null) {
                    retrofit = new Retrofit.Builder()
                            .baseUrl("https://api.example.com/") // 默认 Base URL
                            .client(getOkHttpClient())
                            .addConverterFactory(GsonConverterFactory.create())
                            .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                            .build();
                }
            }
        }
        return retrofit;
    }

    public static OkHttpClient getOkHttpClient() {
        if (okHttpClient == null) {
            synchronized (RetrofitClient.class) {
                if (okHttpClient == null) {
                    OkHttpClient.Builder builder = new OkHttpClient.Builder()
                            .connectTimeout(10, TimeUnit.SECONDS)
                            .readTimeout(10, TimeUnit.SECONDS)
                            .writeTimeout(10, TimeUnit.SECONDS);

                    // 添加缓存(10MB)
                    File cacheDir = new File(System.getProperty("java.io.tmpdir"), "http-cache");
                    builder.cache(new Cache(cacheDir, 10 * 1024 * 1024));

                    // 添加日志拦截器(仅在 Debug 模式下启用)
                    if (BuildConfig.DEBUG) {
                        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
                        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
                        builder.addInterceptor(logging);
                    }

                    okHttpClient = builder.build();
                }
            }
        }
        return okHttpClient;
    }

    /**
     * 动态修改 Base URL
     */
    public static void setBaseUrl(String baseUrl) {
        retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(getOkHttpClient())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .build();
    }

    /**
     * 动态修改 OkHttp 配置
     */
    public static void setOkHttpClient(OkHttpClient client) {
        okHttpClient = client;
        retrofit = new Retrofit.Builder()
                .baseUrl(retrofit.baseUrl().toString())
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .build();
    }
}

NetworkHelper:支持自定义错误处理器

import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.schedulers.Schedulers;
import io.reactivex.rxjava3.disposables.Disposable;

public class NetworkHelper {
    /**
     * 发起网络请求
     *
     * @param single         RxJava 的 Single 对象
     * @param successHandler 成功回调
     * @param errorHandler   失败回调
     * @return Disposable 对象,用于取消订阅
     */
    public static <T> Disposable request(Single<T> single, OnSuccess<T> successHandler, OnError errorHandler) {
        return single.subscribeOn(Schedulers.io()) // 在 IO 线程执行网络请求
                .observeOn(AndroidSchedulers.mainThread()) // 在主线程处理结果
                .subscribe(
                        successHandler::onSuccess, // 成功回调
                        throwable -> errorHandler.onError(handleError(throwable)) // 失败回调
                );
    }

    /**
     * 统一处理错误
     */
    private static String handleError(Throwable throwable) {
        if (throwable instanceof IOException) {
            return "网络连接失败,请检查网络设置";
        } else if (throwable instanceof HttpException) {
            return "服务器错误,请稍后重试";
        } else {
            return "未知错误:" + throwable.getMessage();
        }
    }

    // 成功回调接口
    public interface OnSuccess<T> {
        void onSuccess(T result);
    }

    // 失败回调接口
    public interface OnError {
        void onError(String errorMessage);
    }
}

ApiServiceHelper

import java.lang.reflect.Proxy;

public class ApiServiceHelper {
    /**
     * 创建 API 服务实例
     *
     * @param serviceClass API 服务接口类
     * @return API 服务实例
     */
    public static <T> T createService(Class<T> serviceClass) {
        return (T) Proxy.newProxyInstance(
                serviceClass.getClassLoader(),
                new Class<?>[]{serviceClass},
                (proxy, method, args) -> {
                    // 通过 Retrofit 创建真正的 API 服务实例
                    T service = RetrofitClient.getRetrofit().create(serviceClass);
                    // 调用方法并返回结果
                    return method.invoke(service, args);
                });
    }
}

ApiResponse:统一封装响应基类

public class ApiResponse<T> {
    private int code; // 状态码
    private String message; // 消息
    private T data; // 数据

    // 无参构造函数
    public ApiResponse() {}

    // 全参构造函数
    public ApiResponse(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    // Getter 和 Setter 方法
    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    // toString 方法
    @Override
    public String toString() {
        return "ApiResponse{" +
                "code=" + code +
                ", message='" + message + '\'' +
                ", data=" + data +
                '}';
    }
}

User.java类

public class User {
    private int id;
    private String name;
    private String email;

    // 无参构造函数
    public User() {}

    // 全参构造函数
    public User(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    // Getter 和 Setter 方法
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    // toString 方法
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

ApiService服务类

import io.reactivex.rxjava3.core.Single;
import okhttp3.MultipartBody;
import okhttp3.ResponseBody;
import retrofit2.http.*;

public interface ApiService {
    // 获取用户信息
    @GET("users/{username}")
    Single<User> getUser(@Path("username") String username);

    // 搜索用户
    @GET("users/search")
    Single<List<User>> searchUsers(@Query("query") String query);

    // 创建用户
    @POST("users")
    Single<User> createUser(@Body User user);

    // 文件上传
    @Multipart
    @POST("upload")
    Single<ApiResponse<String>> uploadFile(@Part MultipartBody.Part file);

    // 文件下载
    @Streaming
    @GET("files/{filename}")
    Single<ResponseBody> downloadFile(@Path("filename") String filename);
}

在业务层调用

public class MainActivity extends AppCompatActivity {
    private Disposable disposable; // 用于保存 Disposable 对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 创建 API 服务实例
        ApiService apiService = ApiServiceHelper.createService(ApiService.class);

        // 发起网络请求
        disposable = NetworkHelper.request(
                apiService.getUser("john_doe"),
                user -> {
                    // 处理成功结果
                    Log.d("User", user.toString());
                },
                errorMessage -> {
                    // 处理错误
                    Log.e("Error", errorMessage);
                }
        );
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 取消网络请求,避免内存泄漏
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp或者vue 使用serialport

参考https://blog.csdn.net/ykee126/article/details/90440499 版本是第一位&#xff1a;否则容易编译失败 node 版本 18.14.0 npm 版本 9.3.1 electron 版本 30.0.8 electron-rebuild 版本 3.2.9 serialport 版本 10.0.0 需要python环境 main.js // Modules to control app…

编程题-计算器(中等)

题目&#xff1a; 给定一个包含正整数、加()、减(-)、乘(*)、除(/)的算数表达式(括号除外)&#xff0c;计算其结果。 表达式仅包含非负整数&#xff0c;&#xff0c; - &#xff0c;*&#xff0c;/ 四种运算符和空格 。 整数除法仅保留整数部分。 解法一&#xff08;栈&…

数据增强术:如何利用大模型(LLMs)来模拟不同的扰动类型以增强信息提取任务的鲁棒性

一、对抗样本库构建 1. 基于LLMs的领域针对性扰动设计对抗样本生成 替换实体、三元组和触发器&#xff08;Replace Entity, Triple, and Trigger&#xff09; 使用LLMs&#xff08;如GPT-4&#xff09;来替换句子中的实体、关系三元组或事件触发器&#xff0c;同时保持其类型不…

深入了解Linux —— git三板斧

版本控制器git 为了我们方便管理不同版本的文件&#xff0c;就有了版本控制器&#xff1b; 所谓的版本控制器&#xff0c;就是能够了解到一个文件的历史记录&#xff08;修改记录&#xff09;&#xff1b;简单来说就是记录每一次的改动和版本迭代的一个管理系统&#xff0c;同…

Windows编程----进程的当前目录

进程的当前目录 Windows Api中有大量的函数在调用的时候&#xff0c;需要传递路径。比如创建文件&#xff0c;创建目录&#xff0c;删除目录&#xff0c;删除文件等等。拿创建文件的CreateFile函数做比喻&#xff0c;如果我们要创建的文件路径不是全路径&#xff0c;那么wind…

MyBatis-Plus分页控件使用及使用过程发现的一个坑

最近维护一个旧项目的时候&#xff0c;出现了一个BUG&#xff0c;经排查后发现是Mybatis-plus分页控件使用的时候需要注意的一个问题&#xff0c;故在本地使用MybatisPlus模拟出现了一下这个问题。 首先&#xff0c;先说一下MyBatis-Plus的使用&#xff1a; 1&#xff09;引入…

服务端和客户端通信(TCP)

服务端 using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks;namespace TeachTcpServer {class Program{static void Main(string[] args){#region 知识点一 …

Windows下配置Flutter移动开发环境以及AndroidStudio安装和模拟机配置

截止 2025/3/9 &#xff0c;版本更新到了 3.29.1 &#xff0c;但是为了防止出现一些奇怪的bug&#xff0c;我安装的还是老一点的&#xff0c;3.19&#xff0c;其他版本的安装同理。AndroidStudio用的是 2024/3/1 版本。 — 1 环境变量&#xff08;Windows&#xff09; PUB_H…

C++11中的Condition_variable

C11中的condition_variable 在C11中&#xff0c;条件变量&#xff08;std::condition_variable&#xff09;是线程同步机制之一&#xff0c;用于在多线程环境中实现线程间的通信和协调。它允许一个或多个线程在某个条件尚未满足时等待&#xff0c;直到其他线程通知条件已经满足…

ROS2-话题学习

强烈推荐教程&#xff1a; 《ROS 2机器人开发从入门到实践》3.2.2订阅小说并合成语音_哔哩哔哩_bilibili 构建功能包 # create package demo_python_pkg ros2 pkg create --build-type ament_python --license Apache-2.0 demo_python_pkg 自己写的代码放在./demo_python_pkg/…

深度学习模型Transformer核心组件—前馈网络FFN

第一章&#xff1a;人工智能之不同数据类型及其特点梳理 第二章&#xff1a;自然语言处理(NLP)&#xff1a;文本向量化从文字到数字的原理 第三章&#xff1a;循环神经网络RNN&#xff1a;理解 RNN的工作机制与应用场景(附代码) 第四章&#xff1a;循环神经网络RNN、LSTM以及GR…

Helm安装chart包到k8s报错“不能重复使用名称,名称已被使用”

一、报错提示如下 “Error: INSTALLATION FAILED: cannot re-use a name that is still in use”,意思是安装chart时提供的名称已存在&#xff0c;不能重复使用同一个名称。 登录后复制 rootiZ:/usr/local/src/my-helm-repo/charts# helm install mymemcached3 memcached -n te…

容器编排革命:从 Docker Run 到 Docker Compose 的进化之路20250309

容器编排革命&#xff1a;从 Docker Run 到 Docker Compose 的进化之路 一、容器化部署的范式转变 在 Docker 生态系统的演进中&#xff0c;容器编排正从“手动操作”走向“自动化管理”。根据 Docker 官方 2023 年开发者调查报告&#xff0c;78% 的开发者已采用 Docker Compo…

对开源VLA sota π0的微调——如何基于各种开源数据集、以及你自己的私有数据集微调π0(含我司的微调实践)

前言 25年2.4日&#xff0c;几个月前推出π0的公司Physical Intelligence (π)宣布正式开源π0及π0-FAST&#xff0c;如之前所介绍的&#xff0c;他们对用超过 10,000 小时的机器人数据进行了预训练 该GitHub代码仓库「 π0及π0-FAST的GitHub地址&#xff1a;github.com/Ph…

VBA使用fso对象合并指定路径的txt文件(含子目录)

图(1) 前几天我跟大家分享了在VBA中如何获取指定类型文件的路径的方法&#xff0c;其中最重要的一个思路就是在处理完当前目录的文件后&#xff0c;再调用程序自身来对子目录进行处理&#xff0c;以此来实现对子目录的无限循环&#xff0c;直至所有文件都处理完毕为止。按照此设…

nginx反向代理功能

如上图所示&#xff0c;当配置好nginx反向代理服务器的时候&#xff0c;客户端向nginx反向代理服务器发送请求&#xff0c;nginx反向代理服务器再向真实服务器转发请求。 nginx作为反向代理就是利用nginx高并发&#xff0c;速度快的特性&#xff0c;让nginx能够承受更多的链接…

deepseek在pycharm中的配置和简单应用

对于最常用的调试python脚本开发环境pycharm&#xff0c;如何接入deepseek是我们窥探ai代码编写的第一步&#xff0c;熟悉起来总没坏处。 1、官网安装pycharm社区版&#xff08;免费&#xff09;&#xff0c;如果需要安装专业版&#xff0c;需要另外找破解码。 2、安装Ollama…

【江协科技STM32】ADC数模转换器-学习笔记

ADC简介 ADC&#xff08;Analog-Digital Converter&#xff09;模拟-数字转换器ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁&#xff0c;ADC是一种将连续的模拟信号转换为离散的数字信号的设备或模块12位逐次逼近型…

八卡5090服务器首发亮相!

AI 人工智能领域热度居高不下。OpenAI 的 GPT - 4 凭强悍语言处理能力&#xff0c;在内容创作、智能客服等领域广泛应用。清华大学团队的 DeepSeek 大模型在深度学习训练优势突出&#xff0c;正促使各行业应用端算力需求向推理主导转变&#xff0c;呈爆发式增长 。 随着 DeepS…

hadoop集群环境配置

目录 VMware虚拟机安装 Xshell安装 网络问题 centos7下载 ---------参考以下视频步骤进行生态搭建---------- 搭建好hadoop01 克隆出hadoop02、hadoop03 启动三台虚拟机 打开终端 输入 记录下各个ip 打开Xshell&#xff0c;新建会话 修改主机名 配置静态IP 主机名称…