OkHttp响应缓存教程:RFC 9111标准缓存、条件缓存命中如何帮你省流量

OkHttp响应缓存教程:RFC 9111标准缓存、条件缓存命中如何帮你省流量 OkHttp响应缓存教程RFC 9111标准缓存、条件缓存命中如何帮你省流量【免费下载链接】okhttpA meticulous HTTP client for the JVM, Android, and GraalVM.项目地址: https://gitcode.com/gh_mirrors/okh/okhttpOkHttp 是面向 JVM、Android 和 GraalVM 的 HTTP 客户端它的响应缓存严格遵循 RFC 9111 标准能把重复请求直接由本地缓存命中彻底省掉一次网络往返。本教程带你搞懂如何开启 OkHttp 缓存、三种缓存命中场景的区别以及条件缓存ETag / 304为什么是省流量的关键。如上图所示OkHttp 的每一个请求都会先经过核心的缓存判断CACHE再决定是否真正走网络NETWORK——这就是省流量的第一步。为什么要用 OkHttp 响应缓存没有缓存时每次请求都要经历 DNS 解析、建连、TLS 握手、下载响应体耗时会高达几百毫秒。启用缓存后缓存命中Cache Hit完全不访问网络响应速度从几百毫秒降到几毫秒流量消耗为 0条件命中Conditional Hit只传一个小小的校验头服务器返回304 Not Modified时响应体为 0 字节流量几乎为零离线可用弱网或无网场景下only-if-cached模式可直接读取本地副本。OkHttp 的缓存默认关闭需要显式启用且目标是RFC 正确 务实的行为遇到规范歧义时与 Chrome/Firefox 等现代浏览器保持一致。一键开启缓存最简单配置方法只需要在构建OkHttpClient时通过cache()指定一个目录和大小上限。以下 Android 示例设置 50 MiB文档原注释2020 年值约 5 美分的手机存储空间val client OkHttpClient.Builder() .cache(Cache( directory File(application.cacheDir, http_cache), maxSize 50L * 1024L * 1024L // 50 MiB )) .build()两个要点缓存目录必须被单个 Cache 实例独占但同一个 Cache 可被多个OkHttpClient共享缓存设计用于跨应用重启持久化无需每次启动都清空。相关源码Cache.kt官方缓存文档见 docs/features/caching.md。三种命中场景Hit、Miss 与 Conditional HitOkHttp 通过EventListener暴露缓存事件三种典型场景如下完整事件流见 docs/features/events.md场景事件序列是否走网络说明Cache HitCallStart →CacheHit→ CallEnd否理想情况直接跳过 DNS、建连、下载Cache MissCallStart →CacheMiss→ 常规网络事件是首次请求、不可缓存或已过期Conditional HitCallStart →CacheConditionalHit→ 网络事件 → 响应体 0 字节 →CacheHit是极小服务器确认未修改返回 304上图展示了正常一次调用的事件顺序当缓存命中时绿色建连区域和紫色响应体下载部分都会被大幅跳过这正是省时间的来源。新鲜度怎么算RFC 9111 的新鲜性规则判断还能不能直接用缓存的逻辑在 CacheStrategy.kt 中核心规则响应带Cache-Control: max-age→ 按该时长计算新鲜期否则带Expires头 → 按到期时间计算否则带Last-Modified头 → 采用 RFC 建议的启发式新鲜期文档年龄响应时间减去最后修改时间的10%带 query 参数的 URL 不使用默认过期时间这类 URL 通常指向动态内容。条件缓存命中ETag 如何帮你省流量这是 OkHttp 响应缓存最精髓的部分。当缓存副本过期stale但携带ETag或Last-Modified时OkHttp 不会傻乎乎地全量重新下载而是发起条件请求有ETag→ 请求头加上If-None-Match: etag优先否则有Last-Modified→ 加上If-Modified-Since: date。服务器对比后发现资源没变就返回304 Not Modified不携带响应体——OkHttp 此时把本地缓存副本作为最终响应返回。一次几 MB 的文件更新检查流量可能只有几十字节的请求头。响应中cacheResponse与networkResponse均非空且仅当状态码为 304 时缓存副本才作为顶层响应。源码实现见 CacheStrategy.kt 中选择校验条件的分支逻辑。 想让缓存效率最大化在服务器端给静态资源返回ETag和合理的max-age是最有效的手段。三种常用 CacheControl 指令CacheControl.kt 提供了三类常用指令配合刷新/离线功能非常好用指令用途noCache强制走网络全量刷新用户点击刷新按钮时使用maxAge(0)只要求服务器校验缓存比 noCache 更省流量onlyIfCached只读本地缓存无缓存则直接返回 504适合离线模式缓存管理与命中率统计Cache实例跟踪三个关键指标帮你量化缓存效果requestCount累计请求数networkCount走了网络的请求数hitCount由缓存满足的请求数。注意条件命中会同时计入 networkCount 和 hitCount——因为既有网络交互也有缓存命中。日常运维操作cache.evictAll()清空全部缓存释放空间遍历cache.urls()可按 URL 前缀精确删除如下拉刷新后只清某个域名cache.delete()彻底删除目录一般只在卸载时调用。常见坑为什么缓存没生效最常见的原因响应体没有读完。只有被完整读取、取消或停滞的响应才会写入缓存请确保try-with-resources关闭了 Response。其他注意点请求或响应任一端的no-store指令都会禁止缓存3xx 重定向类响应需要Expires、max-age或public/private头才允许缓存如果请求自己带了If-None-Match等条件头内置缓存将不参与由你的代码自行处理。更多细节见官方缓存文档 docs/features/caching.md 的 Troubleshooting 章节规范遵循情况见 README.md 中对 RFC 9110 / 9111 / 9112 的说明。小结OkHttp 响应缓存遵循RFC 9111默认关闭cache(Cache(目录, 大小))一行开启新鲜期内直接命中省掉全部网络过期后条件命中ETag 304让响应体归零善用maxAge(0)/onlyIfCached平衡刷新与离线体验记住响应要读完才入库并用 hitCount 验证缓存收益。掌握这套机制后你的应用可以在不牺牲数据实时性的前提下显著降低流量消耗与首屏延迟。【免费下载链接】okhttpA meticulous HTTP client for the JVM, Android, and GraalVM.项目地址: https://gitcode.com/gh_mirrors/okh/okhttp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考