剖析OkHttp缓存机制

发表于 5年以前  | 总阅读数:1395 次

原文链接 : WHAT’S UNDER THE HOOD OF THE OKHTTP’S CACHE?

现在应用市场上的 App 无一不需要网络操作,这些应用的开发者大多数都选择结合使用 OkHttpRetrofit 来完成网络操作。okHttp 最为人称道的一个特性就是它的缓存机制,而我将在本篇博文对其进行剖析。

每次我用 OkHttp 时我都需要一些时间想想我将怎么使用它,我该用哪一个 HTTP 报头,作为一个客户端 App 我有哪些职责,我期望从服务器上获得什么,等等……所以对我来说,这篇博文将是 OkHttp 缓存特性的引用文档,我写这篇文档不是因为我在之后的开发中可能会接触 OkHttp 的缓存机制,而是因为我很有可能在下次需要使用它的时候却把这些知识忘了。

这篇博文用于帮助熟悉 OkHttp 的高级工程师,我希望这篇博文的读者最起码应该知道怎么使用 OkHttp 以及怎么开启缓存。如果你不知道的话,就去 OkHttp 的维基页面学习吧。当然了,这里面的解释可能有一部分是错的,我只是尝试去解释一些我所理解的内容,所以如果你发现我某些部分的解释是有问题的,请通过邮件或其他方式告诉我。

分析的起点

我将会从以下类开始我的分析工作:CacheStrategy 和 HttpEngine,其中 CacheStrategy 包含缓存机制的所有逻辑,HttpEngine 是 CacheStrategy 被调用的地方。

  • CacheStrategy.Factory 理解缓存候选响应的报头并将其转换为类成员的构造器
  • CacheStrategy.getCandidate() - 检查缓存候选响应,如果需要的话讲修改原始请求的报头

这两部分内容是 OkHttp 整个缓存机制最关键的部分,而且几乎包含了所有我们想要了解的信息。虽说其他方法也很重要,但如果你去分析的话会发现最终还是会回到这里。

什么是缓存候选响应?

第一次进行 HTTP 请求时不会存在任何已缓存内容,相关 API 只在有缓存内容的时候才会被调用,这点相信不需要我再多解释了。

一旦响应被存储我们就能尝试将它用到后续的调用中,当然了,我们不可能将所有响应码对应的响应都存储下来。我们只存储以下响应码对应的响应:200, 203, 204, 300, 301, 404, 405, 410, 414, 501, 308。除此以外还有 302, 307,但存储它们对应的响应时必须满足以下条件之一:

  • contains Expires header OR

  • CacheControl contains max-age OR

  • CacheControl contains public OR

  • CacheControl contains private

  • 包含 Expires 报头

  • CacheControl 包含 max-age

  • CacheControl 包含 public

  • CacheControl 包含 private

需要注意:OkHttp 的缓存机制不支持缓存部分报文内容。

当我们重复某个请求,OkHttp 会判断是否已经有已缓存的响应,后文中我将称其为缓存候选响应。

CacheStrategy 是什么?

CacheStrategy 需要一个新的报文和一个缓存候选响应,评估这两个 HTTP 报头是否有效并比较它们。

首先,存放在缓存候选响应报头中的部分成员是:

  • Date
  • Expires
  • Last-Modified
  • ETag
  • Age

下面是需要检查的条件的汇总列表:

  1. 判断缓存候选响应是否存在。
  2. 如果接收的是 HTTPS 请求,如果需要的话,判断缓存候选响应是否已进行握手。
  3. 判断缓存候选响应是否已缓存;这和 OkHttp 存储响应时完成的工作是相同的。
  4. 如果没有缓存,在请求报头的 Cache-Control 中检查对应内容,如果该标记为 true,缓存候选响应将不会被使用,后面的检查也会跳过。
  5. 在请求报头中查找 If-Modified-Since 或 If-None-Match,如果找到其中之一,缓存候选响应将不会被使用,后面的检查也会跳过。
  6. 进行一些计算以得到诸如缓存响应缓存响应存活时间,缓存存活时间,缓存最大失活时间。我不希望在此解释所有对应实现的细节,因为这会让博文变得冗长,你只需要知道以上提到的报文内容(例如:Date, Expires 等等…)还有请求 Cache-Control 中的 max-age, min-fresh, max-stale 这部分相关的计算耗时是毫秒级的。完成检查最简单的办法是写这样的伪代码:if ("cache candidate's no-cache" && "cache candidate's age" + "request's min-fresh" < "cache candidate's fresh lifetime" + "request's max-stale")

如果上述条件被满足,那么已缓存的响应报文将会被使用,后面的检查将跳过。 7. 在需要进行网络操作时,下一次检查会判断它是否为“条件请求”。条件请求指的是:发送报文请求服务器响应,而服务器可能会也可能不会返回新的内容,或让我们使用已缓存的报文。

WE LOOK FOR ANDROID DEVELOPERS!

条件请求

下一节看起来是新的内容,但在代码结构中和上一节所解释内容是在相同的方法里的。

  1. 如果缓存候选响应包含 ETag 报头,那么新的 If-None-Match 请求报文会使用相同的 ETag 值。
  2. 如果上一点没有被满足,且缓存候选响应包含 Last-Modified,那么新的 If-Modified-Since 请求报文会使用该值。
  3. 如果以上两点都没有被满足,且缓存候选响应包含 Date,那么新的 If-Modified-Since 请求报文会使用该值。

还有更多!

上述描述过程的最后,也就是 CacheStrategy.getCandidate() 方法返回后,还会有一个检查。OkHttp 会在此时判断报头的 Cache-Strategy 是否包含 “only-if-cached“ 参数。如果有的话,不会请求新的数据。OkHttp 会强制使用缓存候选响应(如果有且可用),不然的话会抛出 HTTP 504 Unsatisfiable Request 错误。

怎么运作?

你可能自己已经知道,进行 HTTP 操作时就是设置正确的报头。但不添加额外的报头内容,使用默认的 HTTP 调用也能完成网络操作,我会在后面提及这部分内容。

无网络环境

刚开始我遇到的问题就包含这个,那时我天真地以为只要允许进行缓存就会解决这个问题,然而并不行,我知道的两种解决方法是:

  • 使用 Cache-Control : only-if-cached header,报文将永远也不会到达服务器。只有存在可用缓存响应时才会检查并返回它。不然的话,会抛出 504 错误,所以开发的时候别忘了处理这个异常。
  • 使用 Cache-Control : max-stale=[seconds] 报头,这种办法更灵活一些,它向客户端表明可以接收缓存响应,只要该缓存响应没有超出其生命周期。而该缓存响应是否可用由 OkHttp 检查,所以不需要与服务器建立连接来判断。但即使如此,当缓存响应超出其生命周期,网络操作还是会进行,然后得到服务器返回的新内容。

关心用户的开销和运行效率

上面提到的解决方法依赖 OkHttp 的验证机制能在离线时完成一些操作。通常 App 都是在线状态,而我们更希望得到新的数据,这样会一次又一次地从服务器上获取相同的内容,给用户产生冗余的开销并降低 App 的运行效率。

理想状态下,我们发送一个请求,得到真正的新数据。当服务器的数据没有发生改变,将得到 304 响应码,而 OkHttp 返回缓存响应。如果服务器支持缓存的话,这种情况是可以实现的。所以你需要做的大体就是和你的同事研究 ETagLast-Modified-Since 是否被支持,如果支持的话,OkHttp 会帮你解决剩下的麻烦!

NOTE: 请不要自己设置 If-Modified-SinceIf-None-Match。前文已经提到,设置这两个报头会跳过后续的许多检查,进行网络操作。

强制网络操作

你也可以强制进行网络操作,但就我个人而言,我还没有这样用过 OkHttp,不过我发现了一些可能的应用场景。例如你在报头中使用了 max-stale,过了很久服务器接收到了该报文。当你想允许用户在某些特殊情况下强行进行刷新时,很简单,在请求中使用 Cache-Control : no-cache,你就能从服务器得到新的数据了。

结论

在我看来,OkHttp 非常易用,极大简化了网络操作。而且有助于理解数据流,哪些报头能被设置以及它们的用处。我希望这篇博文能给你提供一些帮助。

祝你好运!

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:8月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:8月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:8月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:8月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:8月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:8月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:8月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:8月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:8月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:8月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:8月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:8月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:8月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:8月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:8月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:8月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:8月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:8月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:8月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:8月以前  |  398次阅读  |  详细内容 »
 相关文章
简化Android的UI开发 4年以前  |  520739次阅读
Android 深色模式适配原理分析 3年以前  |  28699次阅读
Android阴影实现的几种方案 1年以前  |  10867次阅读
Android 样式系统 | 主题背景覆盖 3年以前  |  9642次阅读
 目录