使用OkHttp 缓存 API 调用提高Android应用性能

使用OkHttp 缓存 API 调用提高Android应用性能

坦率地说,我们都遇到过这样的情况——焦急地刷新应用,看着加载图标不停地旋转,等待那个至关重要的 API 响应。这样的等待我们已经是炉火纯青了,是吧?手指有节奏地轻敲屏幕,微微转动着眼珠,嘴里不那么轻声地嘀咕着:“拜托,赶紧给我数据!”构建与外部 API 交互的应用时,缓存可谓是一项利器。API 调用往往速度缓慢、资源占用大,还受到 API 提供者的速率限制。但是,通过实施强大的缓存机制,你可以极大地减少 API 调用的次数、降低响应时间,并提供更加流畅的用户体验。解决重复 API 调用问题的方法之一就是在本地缓存/存储它们的响应。本文将介绍如何利用 OkHttp 库的 CacheControl 类来存储具有时间有效性的 API 响应。

实施缓存

定义缓存大小和实例

要能够将 API 调用的响应本地存储到缓存中,首先,我们需要定义缓存并通知客户端。在下面的代码片段中,我们使用 okhttp 库中的 Cache 类定义了缓存。我们将此缓存的最大大小设置为 5 MB。然后,在初始化 okhttpclient 参数时使用 cache() 函数。

//OkHttpClient.kt
// Defining a cache of 5 MB size
val cacheSize = (5 * 1024 * 1024).toLong()//Initializing instance of Cache class
val myCache = Cache(context.cacheDir, cacheSize)//defining okhttpclient instance
val okHttpClient = OkHttpClient.Builder().cache(myCache).build()

定义缓存规则

根据设备是否连接到互联网,让我们来定义一些基本的网络缓存规则:

  • 如果设备连接到互联网:如果最后一次 API 响应是在不到 30 分钟之前检索的,则显示缓存的响应;否则,获取新的响应并将其存储在缓存中。
  • 如果设备离线:使用最多 1 天前的 API 响应以保持应用程序功能。

你可以为你的项目定义不同且更为细致的规则来应对复杂的情况,但为了简单起见,我们将采用上述规则。

第一步是检查用户是否连接到互联网。为此,我们可以使用 ConnectivityManager 类收集数据并检查用户是否连接到互联网。让我们来定义一个名为 hasNetwork() 的函数,如下所示:

//CheckNetwork.kt
fun hasNetwork(context: Context): Boolean {val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManagerval nw      = connectivityManager.activeNetwork ?: return falseval actNw = connectivityManager.getNetworkCapabilities(nw) ?: return falsereturn when {actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> trueactNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> trueactNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> trueactNw.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> trueelse -> false}
}

我们检查用户是否连接到WiFi、蜂窝移动网络或蓝牙网络,并根据情况返回true或false。

为了实现我们缓存规则的定义,我们将使用 OkHttp 库中的一个组件,叫做 Interceptor。拦截器是一个强大的机制,允许您在应用程序发送或接收 HTTP 请求和响应之前拦截、处理甚至修改它们。它们在通信流程中起到中间人的作用,让您更加灵活地控制 OkHttp 处理网络请求的方式。

在拦截器中,我们将提供指导,告诉我们的 okHttpClient 实例何时使用缓存响应。

在构建客户端实例时,让我们使用 addInterceptor() 函数来添加拦截器。我们可以在这个函数中修改我们的 API 请求。在 lambda 函数中,我们可以获取请求对象,并在最终发送到服务器之前对其进行修改。为了添加缓存功能,我们使用 cacheControl() 函数,该函数接受 CacheControl 类的参数。

我们需要实现的第一条规则是,如果设备连接到互联网,则使用 30 分钟前的响应(如果有的话),否则获取新的响应。我们使用 maxAge() 函数来实现这一点。

我们需要实现的第二条规则是,如果设备断开连接,则使用最多 1 天前的响应。为此,我们使用 maxStale() 函数。

// Defining a cache of 5 MB size
val cacheSize = (5 * 1024 * 1024).toLong()//Initializing instance of Cache class
val myCache = Cache(context.cacheDir, cacheSize)//defining okhttpclient instance
val okHttpClient = OkHttpClient.Builder().cache(myCache).addInterceptor { chain ->var request = chain.request()request = if (hasNetwork(context))request.newBuilder().cacheControl(CacheControl.Builder().maxAge(30, TimeUnit.MINUTES).build()).build()elserequest.newBuilder().cacheControl(CacheControl.Builder().maxStale(1, TimeUnit.DAYS).build()).build()chain.proceed(request)}.build()

maxAge() 与 maxStale() 的区别

max-agemax-stale 是 HTTP 缓存中用来控制响应新鲜度的指令。它们有着不同的含义:

  • max-age:指定客户端认为缓存响应是新鲜的最大时间,以秒为单位。如果响应的年龄超过了 max-age,客户端将认为该响应已过期,并尝试从服务器获取新的响应。

  • max-stale:告知客户端即使响应已过期,仍可接受,但仅在指定的最大过期时间内。同样以秒为单位。

以上是它们的区别。现在我们已经在 OkHttpClient 中实现了缓存系统,是时候为你的项目构建一个快速可靠的用户体验了。如果你使用 Retrofit 作为 OkHttp 的封装器,也可参考以下代码片段来实现缓存!

//RetrofitClient.kt 
class RetrofitClient(private val context: Context) {val cacheSize = (5 * 1024 * 1024).toLong()val instance: Api by lazy {val myCache = Cache(context.cacheDir, cacheSize)val okHttpClient = OkHttpClient.Builder().cache(myCache).addInterceptor { chain ->var request = chain.request()request = if (hasNetwork(context))request.newBuilder().cacheControl(CacheControl.Builder().maxAge(30, TimeUnit.MINUTES).build()).build()elserequest.newBuilder().cacheControl(CacheControl.Builder().maxStale(1, TimeUnit.DAYS).build()).build()chain.proceed(request)}.addInterceptor(HttpLoggingInterceptor().apply {this.level = HttpLoggingInterceptor.Level.BODY }).build()val retrofit = Retrofit.Builder().baseUrl("BASE_URL").addConverterFactory(GsonConverterFactory.create()).client(okHttpClient).build()retrofit.create(Api::class.java)}
}

现在,你可以开始在实际设备或模拟器上运行你的项目了。要检查缓存是否有效,请使用Android Studio中的App Inspection标签页,或者使用OkHttp的日志拦截器来记录所有网络调用。

结论

对于长时间不变的API响应,可以通过上述技术进行缓存,从而节省大量资源。软件开发始终涉及根据时间和空间做出一定的权衡。在这种情况下,我们为了节省时间而牺牲了一点空间(用于存储API响应)。

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

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

相关文章

《R语言与农业数据统计分析及建模》——多重共线性和逐步回归

一、多重共线性 多重共线性:在多元线性回归时,多个自变量之间存在高度相关关系,时模型估计失真或难以估计准确的情况。 一般地,多元线性回归中自变量间应尽量相互独立。常规模型诊断方法难以检测多重共线性。 1、案例解释 作物产…

ActiveMQ 反序列化漏洞 (CVE-2015-5254)

一、漏洞描述 Apache ActiveMQ 是由美国阿帕奇(Apache)软件基金会开发的开源消息中间件,支持 Java 消息服务、集群、Spring 框架等。属于消息队列组件(消息队列组件:分布式系统中的重要组件,主要解决应用耦合、异步消息…

MySQL个人复习总结

最近想把MySQL的知识点再过一遍,带着自己的理解使用简短的话把一些问题总结一下,尤其是开发中和面试中的高频问题,基础知识点可以参考之前写的如下几篇博客,这篇不再赘述,阅读顺序由浅入深依次递进。 一、MySQL 概述 数据库&表操作 数据增删改; 二、MySQL 单表查询 …

VUE3与Uniapp 五 (v-if、v-show和template、v-for的使用)

<template><!-- v-if如果是false&#xff0c;则不会出现在DOM中&#xff0c;不会被渲染&#xff1b;v-show如果为false&#xff0c;则会出现在DOM中&#xff0c;并加载资源&#xff08;如图片&#xff09;&#xff0c;只是CSS隐藏了。 --><view v-if"day1&…

【Vue】Pdf转图片功能+多张图片拼接封装

Pdf转图片功能多张图片拼接封装 HTML页面tools.js文件 HTML页面 <template><div class"main-marge"><div class"box"><van-uploader accept"image/*,.pdf" :before-read"(file) > beforeRead(file, -1)">…

数据库|TiDB-Server API的高效应用指南

一、API介绍 1.Status 显示TiDB 连接数、版本和git_hash 信息 tidb-server_ip:status_port/status { "connections": 0, "version": "5.7.25-TiDB-v6.1.1", "git_hash": "5263a0abda61f102122735049fd0dfadc7b7f822" } 2.St…

mysql-sql-练习题-4-标记

标记 连续登录2-7天用户建表排名找规律 最大连胜次数建表只输出连胜结果输出所有连续结果 连续登录2-7天用户 建表 create table continuous_login(user_id1 integer comment 用户id,date_login date comment 登陆日期 ) comment 用户登录表;insert into continuous_login val…

LT2611UX四端口 LVDS转 HDMI2.0,带音频

描述LT2611UX 是一款面向机顶盒、DVD 应用的高性能 LVDS 至 HDMI2.0 转换器。LVDS输入可配置为单端口、双端口或四端口&#xff0c;具有1个高速时钟通道和3~4个高速数据通道&#xff0c;工作速率最高为1.2Gbps/通道&#xff0c;可支持高达19.2Gbps的总带宽。LT2611UX 支持灵活的…

002 springCloudAlibaba Sentinel流控-关联

当与A关联的资源B达到阀值后&#xff0c;就限流A自己 文章目录 FlowLimitController.javaSentinelServerApplication.javaServletInitializer.javaapplication.yamlpom.xmlpom.xml 启动Sentinel8080 - java -jar sentinel-dashboard-1.7.0.jar 启动微服务8401 启动8401微服务…

一款非常不错的音频录制播放Python库

声音无处不在&#xff0c;在计算机应用中也是。Python拥有丰富的库来处理声音&#xff0c;sounddevice就是其中一个非常实用的库。本文将介绍sounddevice库的特点、工作原理以及使用方式&#xff0c;帮助你大家理解和运用这个库。 简介 sounddevice是一个Python库&#xff0c…

72、栈-每日温度

思路&#xff1a; 第一种方法&#xff0c;双循环&#xff0c;第一层循环拿出一个元素&#xff0c;第二层循环寻找最近比当前大的元素位置。 第二种方法&#xff1a;使用栈来实现。 初始化&#xff1a; int[] ans 用来存储每一天之后多少天温度会升高。Stack<Integer> 用…

软件重构的要点及注意事项

重构是软件开发过程中改进现有代码结构和设计而不改变其外在行为的过程。良好的重构实践可以提高代码质量、可读性、可维护性&#xff0c;并促进后续的开发工作。以下是重构的基本步骤、要点及注意事项&#xff1a; 重构的基本步骤 明确重构目的&#xff1a;确定重构的动机&a…

Java | AI+编程 | 如何使用通义灵码提升开发效率

大家好&#xff0c;我是程序员影子 | 全网同名 一名致力于帮助更多朋友快速入门编程的程序猿 今天&#xff0c;我将以小白入门的视角带着大家学会如何在Idea上使用通义灵码&#xff0c;提高开发效率&#xff0c;减少重复工作&#xff1b;话不多说&#xff0c;我们直接进入正题…

点云和去噪

1. 什么是去噪 在人工智能领域中&#xff0c;去噪指的是利用算法和模型来消除或减少数据中的噪声&#xff0c;以提高数据的质量和可用性。噪声是指数据中不希望的随机扰动或干扰&#xff0c;可能由于采集过程中的各种因素引入&#xff0c;例如传感器误差、环境干扰、信号衰减等…

golang beego结合wire依赖注入及自动路由

1 安装wire 1.1 通过命令直接安装 go install github.com/google/wire/cmd/wirelatest 1.2 通过go get方式安装 go get github.com/google/wire/cmd/wire进入目录编译 cd C:\Users\leell\go\pkg\mod\github.com\google\wirev0.6.0\cmd\wire go build 然后将wire.exe移动到…

广交会烹饪机器人用上大模型 支付宝小程序云提供技术支持

近日&#xff0c;第135届广交会正在火热进行&#xff0c;记者获悉&#xff0c;支付宝小程序云助力合作伙伴田螺云厨&#xff0c;在烹饪机器人上开始用上大模型技术。各类智能产品的亮相&#xff0c;从中国制造迈向中国创造&#xff0c;也成为广交会的一个亮点。 &#xff08;图…

鲲鹏华为云--OBS

文章目录 1.创建桶2.上传对象3.下载对象4.分享对象5. 删除对象6.删除桶 1.创建桶 创建桶 2.上传对象 点击创建的桶–“上传对象” 拖拽本地文件或文件夹至“上传对象”区域框内添加待上传的文件。 也可以通过单击“上传对象”区域框内的“添加文件”&#xff0c;选择本地…

给vue配置路径别名@

使用vite构建的项目 在vite.config.js中进行别名的配置 import { defineConfig } from vite import vue from vitejs/plugin-vueexport default defineConfig({plugins: [vue()],resolve: {alias: {: /src}} }) //这样&#xff0c;你就可以使用作为别名来引用/src目录下的文件…

C语言函数指针的使用、函数指针数组及使用、指向函数指针数组的指针,指针进阶版的冒泡排序等介绍

文章目录 前言一、函数指针的使用1. 加减乘除计算器普通实现2. 加减乘除计算机函数指针实现 二、函数指针数组1. 函数指针数组的书写2. 两个有趣的代码3. 函数指针数组的使用 三、指向函数指针数组的指针四、指针进阶_冒泡排序1.整型冒泡排序2. C语言qsort函数3. 仿写C语言qsor…

ChatGLM2-6B的部署步骤_A3

ChatGLM2-6B 下载地址 一、VisualGLM-6B环境安装 1、硬件配置 操作系统&#xff1a;Ubuntu_64&#xff08;ubuntu22.04.3&#xff09; GPU&#xff1a;4050 显存&#xff1a;16G 2、配置环境 建议最好自己新建一个conda环境 conda create -n chatglm2 python3.8pip …