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

news2024/11/25 2:52:08

使用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 ConnectivityManager
        val nw      = connectivityManager.activeNetwork ?: return false
        val actNw = connectivityManager.getNetworkCapabilities(nw) ?: return false
        return when {
            actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
            actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
            actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
            actNw.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> true
            else -> 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()
                else
                    request
                        .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()
                else
                    request
                        .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.coloradmin.cn/o/1633940.html

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

相关文章

【Node.js工程师养成计划】之express框架

一、Express 官网:http://www.expressjs.com.cn express 是一个基于内置核心 http 模块的,一个第三方的包,专注于 web 服务器的构建。 Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用&…

LabVIEW机械臂控制与图像处理示教平台

LabVIEW机械臂控制与图像处理示教平台 随着工业自动化技术的快速发展,工业机器人在制造业中的应用越来越广泛,它们在提高生产效率、降低人工成本以及保证产品质量方面发挥着重要作用。然而,传统的工业机器人编程和操作需要专业知识&#xff…

React正式更新!开始学习React 19!

本文为原创文章,原文链接:J实验室,未经授权请勿转载 今年2月份,React 发布消息确认今年发布 v19 版本,尘封两年的版本号终于要更新了(详情点击:React 19 发布在即,抢先学习一下新特性…

FSNotes for Mac v6.7.1中文激活版:强大的笔记管理工具

FSNotes for Mac是一款功能强大的文本处理与笔记管理工具,为Mac用户提供了一个直观、高效的笔记记录和整理平台。 FSNotes for Mac v6.7.1中文激活版下载 FSNotes支持Markdown语法,使用户能够轻松设置笔记格式并添加链接、图像等元素,实现笔记…

Linux下启动jenkins报错问题解决

jenkins端口报错 java.io.IOException: Failed to start Jettyat winstone.Launcher.<init>(Launcher.java:209)at winstone.Launcher.main(Launcher.java:496)at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at java.base/jdk.int…

【氮化镓】AlGaN/GaN HEMTs沟道温度测量

文章是关于AlGaN/GaN HEMTs&#xff08;高电子迁移率晶体管&#xff09;在不同基底&#xff08;如蓝宝石和硅&#xff09;上生长时&#xff0c;通过直流&#xff08;DC&#xff09;特性方法确定沟道温度的研究。文章由J. Kuzmk, P. Javorka, A. Alam, M. Marso, M. Heuken, 和 …

微软如何打造数字零售力航母系列科普04 - 微软联合Adobe在微软365应用程序中工作时推出新的生成式AI功能

微软和Adobe正在合作&#xff0c;将情境营销见解和工作流程引入微软Copilot&#xff0c;以提供生成的人工智能功能&#xff0c;使营销人员和营销团队能够在自然的工作流程中实现更多目标。 这些新的集成功能将在生产力和协作工具&#xff08;如Outlook、Teams和Word&#xff0…

JAVA基础——集合框架(List与Set)

数据结构 什么是数据结构 数据结构就是用来装数据以及数据与之间关系的一种集合。如何把相关联的数据存储到计算机&#xff0c;为后续的分析提供有效的数据源&#xff0c;是数据结构产生的由来。数据结构就是计算机存储、组织数据的方式。好的数据结构&#xff0c;让我们做起事…

使用QT完成如图的游戏登录界面 使用信号和槽完成密文明文密码转换,重置账号和密码,登录校验 详细代码在主页下载

头文件: #ifndef LOGINWIDGET_H #define LOGINWIDGET_H #include <QLineEdit> #include <QPushButton> #include <QWidget> class LoginWidget : public QWidget {Q_OBJECT public: LoginWidget(QWidget *parent = 0); ~LoginWidget(); public slots: …

基于uniapp+微信小程序的智能停车场管理小程序,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Three.js杂记(十五)—— 汽车展览(下)

在上一篇文章Three.js杂记&#xff08;十四&#xff09;—— 汽车展览上 - 掘金 (juejin.cn)中主要对切换相机不同位置和鼠标拖拽移动相机焦点做了简单的应用。 那么现在聊聊该如何实现汽车模型自带的三种动画展示了&#xff0c;实际上可以是两种汽车前后盖打开和汽车4车门打开…

C# APS.NET CORE 6.0 WebApi在IIS部署报错

今天尝试着把基于 APS.NET CORE6.0开发的webAPI程序部署到IIS中&#xff0c;当打开网站地址时报错&#xff0c;无法打开&#xff0c;于是查找资料最终进行了解决。 打开 IIS →模块 查看列表中是否存在 AspNetCoreModuleV2&#xff0c;如下&#xff1a; 对应的应用池需要选择“…

小程序SSL证书更新指南

随着网络技术的不断发展&#xff0c;小程序已经成为许多企业和个人进行业务推广和服务提供的重要平台。在享受小程序带来的便利和高效的同时&#xff0c;我们也必须重视其安全性问题。SSL证书作为保障小程序数据传输安全的重要手段&#xff0c;其更新工作不容忽视。本文将为大家…

Android log tag标签如am_pss意义

Android log tag标签如am_pss意义 Android输出日志中不同的标签代表不同的意义&#xff0c;比如 am_pss&#xff0c;则代表内存回收&#xff08;整理&#xff09;。定义在源代码文件 &#xff1a; https://android.googlesource.com/platform/frameworks/base//master/servic…

字节5面挂,恶心到了。。。

字节五面 今天脉脉看到一篇帖子&#xff1a; 楼主是 tx 的前员工&#xff0c;在字节五面&#xff08;加轮&#xff09;被挂后&#xff0c;认定&#xff08;或许私下做了一些调查&#xff09;是字节 HR 向 tx 背调&#xff0c;然后被前同事捏造虚假信息&#xff0c;导致的面试失…

初识MVC

初识MVC 理论部分 今天第一次学MVC&#xff0c;拿到一个练手项目。现在来记录一下学习过程。 项目的背景就是个学生管理系统。我只做后端。 从大的来说MVC将应用程序分为三个主要组件&#xff08;部分&#xff09;&#xff1a; 模型&#xff08;Model&#xff09;是应用程序…

UE5像素流部署以及多实例部署(兼容ue4)

像素流部署请看我之前的文章就行&#xff0c;今天讲的是多实例部署 在这里可以配置多实例的数量 如果设置800端口 设置两个实例 那么就是800 801端口 我的个人显卡是4060TI,最多开三个

张大哥笔记:服务器有挖矿木马程序,该如何处理?

这篇文章发表于2021年&#xff0c;今天借这个平台再发布一下&#xff0c;希望对大家有所帮助&#xff01; 今天收到一个粉丝求助&#xff0c;说收到了阿里云官方短信通知提示有挖矿程序&#xff0c;要求立即整改&#xff0c;否则会关停服务器&#xff0c;以下是我和他的对话内…

238 基于matlab的水平轰炸弹道的求解

基于matlab的水平轰炸弹道的求解&#xff0c;列出轰炸弹道方程组并利用龙格库塔法解算弹道方程。设计中包含了二维弹道与三维弹道的计算&#xff0c;并都绘制了弹道运动轨迹&#xff0c;最终还将整个题目集中在一个图形用户界面&#xff08;GUI&#xff09;上。程序已调通&…

CTFHub-Web-SSRF

CTFHub-Web-SSRF-WP 一、内网访问 1.题目提示说访问127.0.0.1的flag.php&#xff0c;在URL后面添加路径没想到直接访问成功 二、伪协议读取文件 1.题目提示说访问Web目录下的flag.php&#xff0c;联想到Web目录一般存放于/var/www/html/里&#xff0c;去修改URL尝试进行访问…