使用 Retrofit 2.0.x 进行 HTTP 缓存

2024-04-23

我正在尝试使用 Retrofit 2.0 在我的应用程序中缓存一些响应,但我遗漏了一些内容。

我安装了一个缓存文件,如下:

private static File httpCacheDir;
private static Cache cache;
try {
    httpCacheDir = new File(getApplicationContext().getCacheDir(), "http");
    httpCacheDir.setReadable(true);
    long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
    HttpResponseCache.install(httpCacheDir, httpCacheSize);
    cache = new Cache(httpCacheDir, httpCacheSize);
    Log.i("HTTP Caching", "HTTP response cache installation success");
} catch (IOException e) {
    Log.i("HTTP Caching", "HTTP response cache installation failed:" + e);
}

public static Cache getCache() {
        return cache;
    }

它创建一个文件/data/user/0/<PackageNmae>/cache/http,然后准备一个网络拦截器如下:

public class CachingControlInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        // Add Cache Control only for GET methods
        if (request.method().equals("GET")) {
            if (ConnectivityUtil.checkConnectivity(getContext())) {
                // 1 day
                request.newBuilder()
                    .header("Cache-Control", "only-if-cached")
                    .build();
            } else {
                // 4 weeks stale
                request.newBuilder()
                    .header("Cache-Control", "public, max-stale=2419200")
                    .build();
            }
        }

        Response originalResponse = chain.proceed(chain.request());
        return originalResponse.newBuilder()
            .header("Cache-Control", "max-age=86400")
            .build();
    }
}

my Retrofit and OkHttpClient实例:

OkHttpClient client = new OkHttpClient();
client.setCache(getCache());
client.interceptors().add(new MainInterceptor());
client.interceptors().add(new LoggingInceptor());
client.networkInterceptors().add(new CachingControlInterceptor());
Retrofit restAdapter = new Retrofit.Builder()
        .client(client)
        .baseUrl(Constants.BASE_URL)
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build();

productsService = restAdapter.create(ProductsService.class);

where ProductsService.class包含:

@Headers("Cache-Control: max-age=86400")
@GET("categories/")
Call<PagedResponse<Category>> listCategories();

and

Call<PagedResponse<Category>> call = getRestClient().getProductsService().listCategories();
call.enqueue(new GenericCallback<PagedResponse<Category>>() {
      // whatever 
      // GenericCallback<T> implements Callback<T>
   }
});

这里的问题是:如何使其在设备离线时访问缓存的响应?

后端响应的标头为:

Allow → GET, HEAD, OPTIONS
Cache-Control → max-age=86400, must-revalidate
Connection → keep-alive
Content-Encoding → gzip
Content-Language → en
Content-Type → application/json; charset=utf-8
Date → Thu, 17 Dec 2015 09:42:49 GMT
Server → nginx
Transfer-Encoding → chunked
Vary → Accept-Encoding, Cookie, Accept-Language
X-Frame-Options → SAMEORIGIN
x-content-type-options → nosniff
x-xss-protection → 1; mode=block

终于我得到了答案。

网络拦截器应如下所示:

public class CachingControlInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        // Add Cache Control only for GET methods
        if (request.method().equals("GET")) {
            if (ConnectivityUtil.checkConnectivity(YaootaApplication.getContext())) {
                // 1 day
               request = request.newBuilder()
                        .header("Cache-Control", "only-if-cached")
                        .build();
            } else {
                // 4 weeks stale
               request = request.newBuilder()
                        .header("Cache-Control", "public, max-stale=2419200")
                        .build();
            }
        }

        Response originalResponse = chain.proceed(request);
        return originalResponse.newBuilder()
            .header("Cache-Control", "max-age=600")
            .build();
    }
}

然后安装缓存文件就这么简单

long SIZE_OF_CACHE = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(new File(context.getCacheDir(), "http"), SIZE_OF_CACHE);
OkHttpClient client = new OkHttpClient();
client.cache(cache);
client.networkInterceptors().add(new CachingControlInterceptor());
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Retrofit 2.0.x 进行 HTTP 缓存 的相关文章

  • 将ForeignCollection 转换为ArrayList - ORMLite、Gson 和 Android

    如果我的解释不太清楚 我深表歉意 但如果需要 我会添加并编辑这个问题以使其清晰 我正在开发一个 Android 应用程序 它通过外部 API 接收数据并使用 ORMLite 在本地存储数据 在本地存储数据并使用 ORMLite 之前 我有一
  • 未找到 ADB screenrecord 命令

    我无法奔跑adb shell screenrecord sdcard my mp4 我尝试运行此命令的设备规格 Honor 5C 安卓6 0 每当我运行 screenrecord 命令时 它都会显示未找到命令 D adb gt adb sh
  • Android 从图库中选择图像显示内存错误

    我正在编写一个代码示例 我必须从图库中选择一个图像 该代码正在运行 但是在从图库中选择图像后 我得到了内存不足错误 in my 活动结果时 我可以获得小图像 但大图像会产生问题 这是我的代码 try Uri selectedImageUri
  • 如何在 PercentRelativeLayout 中使用layout_aspectRatio?

    我尝试在视图上实现 16 9 的纵横比PercentRelativeLayout https developer android com reference android support percent PercentRelativeLa
  • Android布局中如何实现Button的自动宽度

    我有几个垂直列出的按钮 我需要它们都具有相同的宽度 而且还要显示其中的所有文本 基本上我需要所有它们的宽度作为最大的宽度的包裹宽度 希望我解释得很好 现在 我已经有一种布局可以在我的 Samsung Galaxy S2 4 1 2 上运行
  • Android中的OpenGL用于视频显示

    是否可以使用 OpenGL 来显示视频并能够在运行时调整视图大小 是的 它的工作原理是通过 glTexSubImage2D 将每个帧作为纹理上传 我已经测试了基于 FFmpeg 的解码器的输出 效果很好
  • 删除所有(子)片段的正确方法

    我在父级片段线性布局 fragmentContainer 中动态加载一堆子级片段 然后当用户单击按钮时 我需要将它们全部删除并添加新的 我不知道每次会添加多少碎片 这是我一次性删除所有碎片的方法 LinearLayout ll Linear
  • Android 3.1 USB 主机 - BroadcastReceiver 未收到 USB_DEVICE_ATTACHED

    我经历过USB 主机的描述和示例位于developer android com http developer android com guide topics usb host html检测连接和分离的 USB 设备 如果我在清单文件中使用
  • 在 Android 中完成一项活动?

    我有一些活动 Home Activity gt Activity 1 gt Activity 2 gt Activity 3 gt HomeActivity finish finish finish Home Activity gt Act
  • Android:Google Maps API 密钥注册:MD5 认证密钥

    如何获取MD5指纹密钥 我正在使用这个命令 C Program Files Java jdk1 7 0 04 bin gt keytool exe list alias androiddebugkey keystore C Document
  • 在 Android Studio 中使用预构建的共享库

    我需要在我的 android 项目中使用自定义的预构建共享库 在独立 ndk 上构建为 libdynamic so 我在路径 src main 中创建了一个文件夹 jniLibs 然后在其中创建了 4 个文件夹 即 armeabi arme
  • Room - LiveData 观察器在数据库更新时不会触发

    我试图在下面的代码中找出 为什么在我用新数据填充数据库后 Room 的 LiveData observable 不会给我新的转变 这是放在我的活动的 onCreate 方法中 shiftsViewModel ViewModelProvide
  • 如何使用android ndk r9b为Android编译FFMPEG

    我想设计一个Android应用程序 可以通过FFMPEG命令播放和编辑视频 但我不知道如何在Android上使用FFMPEG 我尝试过从Google搜索到的许多方法 但它们太旧了 无法实现 现在 FFMPEG的最新版本是2 1 1 Andr
  • 如何在Android上获取角度中的按键事件?

    我们如何在 Android 上的 Angular 中获取按键事件及其值 我使用phonegap Cordova Angular JS
  • Kotlin 协程阻塞 Android 中的主线程

    我是 Kotlin 和协程的新手 我有一个fun在我的活动及其内部 检查User用户名和密码 如果为真 则返回Users object 一切都好 但是当我按下按钮时 我的活动被阻止并等待响应Users login 我用这个有趣的 priva
  • Kotlin 中的枚举类对于 Android 来说是否像 Java 中那样“昂贵”?

    Are EnumKotlin 中的类对于 Android 来说 昂贵 就像 Java 一样 还可以用吗 IntDefs or StringDefs在科特林 当我将 Kotlin Enum 类反编译为 Java 类时 底层仍然使用了 Java
  • Android Studio 1.0 在 dexDebug 或 dexRelease 上构建失败

    我最近从 Android Studio 0 9 2 升级到 1 0 包括 Gradle 插件版本 1 0 0 并且在构建项目时遇到问题 每当我构建时 我都会在 dexDebug 或 dexRelease 步骤中收到以下异常 UNEXPECT
  • Android:如何停止监听电话监听器? [复制]

    这个问题在这里已经有答案了 可能的重复 Android 为什么 PhoneCallListener 在活动完成后仍然存在 https stackoverflow com questions 11666853 android why phon
  • 超慢的表格布局性能

    我遇到了糟糕的 TableLayout 性能 我在这里读过一些帖子 谈论同样的事情 Android 动态创建表 性能不佳 https stackoverflow com questions 9813427 android dynamical
  • Android Wear Overlay 传递触摸事件

    我有一个 Android Wear 应用程序 其中我使用透明的覆盖视图来接收触摸事件 我需要能够接收屏幕上任何位置发生的所有触摸事件 并且还能够看到它们的坐标 我发现的所有研究都表明我无法接收所有触摸事件并将其传递 然而 and 都在做这样

随机推荐

  • Safari 在 div 中使用 Google 地图打破边框半径

    对我来说关于 Stack 的第一个问题 我已经完成了我的作业并发现了类似这个主题的内容 在 webkit 浏览器中 v3 谷歌地图不尊重容器的边框半径 有人有解决方法吗 https stackoverflow com questions 1
  • 查找API端点的方法

    API探索 尽管有几个问题涉及该主题 但我找不到解决我想要理解的核心概念的问题 如果知道 API 的根结构 我们可以想象一下http stackoverflow com api service 我们可以成功地从已知端点检索结果 比方说htt
  • 如何安全地销毁 QThread?

    我想正确地销毁一个QThread在 Qt 5 3 中 到目前为止我已经得到 MyClass MyClass QObject parent QObject parent mThread new QThread this QObject con
  • 获取 3 个列表之间的差异

    我正在研究列表的差异 gt gt a 1 2 3 gt gt b 2 4 5 gt gt c 3 2 6 两组之间的对称差异可以使用以下方法完成 gt gt z set a symmetric difference set b gt gt
  • 3D 空间中的激光投影仪校准

    我正在研究一种在现实世界中校准激光投影仪的解决方案 该项目有几个目标 1 Take in a minimum of four points measured in the real world in 3d space that repres
  • dojo.parser.parse 仅在第一次调用时工作

    我有一个页面 当用户单击某些报告工具的链接时 它首先要求他们输入一些报告参数 我根据链接的 id 使用 AJAX 以表单形式获取参数对话框 每个对话框上都有一些 dojo 控件 因此我需要在对话框出现时解析它们 因为它最初不是页面的一部分
  • 可以在 Mathematica 中扩展 PDF、CDF、FindDistributionParameters 等功能吗?

    我开始使用新的 Mathematica 统计和数据分析功能进行越来越多的工作 我周二参加了 Mathematica 统计与数据分析 在线研讨会 非常棒的演讲 我强烈推荐 但我遇到了一些问题 我希望这个论坛上的人可以花点时间考虑一下 我创建了
  • VSO/VSTS:在主机代理上使用发布构建工件时出错

    使用 发布构建工件 任务时 构建中会引发以下错误 就在 获取源 之后 任务的定义没有与任何匹配的处理程序 由该代理支持 支持的处理程序 AzurePowerShell AzurePowerShellHandler PowerShell Po
  • 创建会话[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我需要在 php 中创建会话的帮助 我需要一个登录会话 然后如果用户想更改他们的用户名 他们可以但是 我知道如何更改用户名 但使用会话时情
  • 如何在 React App 完成加载之前显示全页加载器/旋转器

    如何制作全页加载器 旋转器 首先加载 然后显示 直到 React 或不同的基于 JS 的框架 应用程序完全加载 完全加载 是指浏览器旋转器停止旋转的那一刻 我正在为非 js 渲染的网站制作这些加载器 旋转器 但我不确定如何为 JS 渲染的应
  • Google 云端点(应用程序引擎)+ oauth2 与 android 集成

    我正在尝试将谷歌应用程序引擎云端点 API 与 android 集成 我已经按照此链接进行了相同的操作 无法使用我的服务对象连接到我的谷歌端点 https stackoverflow com questions 29544723 unabl
  • 你能强制 Vim 在文件末尾显示一个空行吗?

    当我在记事本中打开文本文件时 如果包含文本的最后一行末尾有回车符 则会显示一个空行 然而 在 Vim 中它不显示这个空行 我注意到的另一件事是 Vim 编辑器默认在最后一行添加回车符 即使它没有显示 我可以这么说 因为如果我在记事本中打开在
  • Java流合并或减少重复对象

    我需要通过将所有重复条目合并到一个对象中来从可以具有重复项的列表中生成一个唯一的朋友列表 Example 从不同的社交源中获取好友并放入 1 个大列表中1 朋友 姓名 约翰尼 德普 出生日期 1970 11 10 来源 FB fbAttri
  • 重新排序/重置自动增量主键

    我有一个带有自动增量主键的 MySQL 表 我删除了表格中间的一些行 例如 现在我在 ID 列中有这样的内容 12 13 14 19 20 我删除了 15 16 17 和 18 行 我想重新分配 重置 重新排序主键 以便具有连续性 即将 1
  • 如何在 mongodb 聚合期间有条件地投影字段

    我有一个用户文档 例如 id s0m3Id skills skill1 skill2 现在我想通过以下方式展开此文档 skills字段并为每项技能添加分数 所以我的汇总看起来像 unwind path skills preserveNull
  • Rest 服务器(Play Framework)在负载测试期间出现“Read Timed out”异常

    我们正在使用 Play Framework 在 REST 服务器上运行重负载测试 jmeter 350 个线程 35M 总请求 并在大约 2 小时后遇到以下错误 我们删除了其他组件 以便 request 只是接受请求而不执行任何操作 任何人
  • JSON 行 Mime 类型

    我想知道为 JSON 行设置什么 Content Type http jsonlines org http jsonlines org 我尝试搜索 它并不是真正的 application json 因为整个内容都不是 JSON 每一行都是
  • 如何从Python使用OpenCV的C++函数?

    我正在使用 OpenCV 的 Python 绑定 它真的很棒 但是 C 版本中的某些函数在 Python 绑定 BackgroundSubstractorMOG2 和许多特征检测算法中缺失 从 Python 调用它们的最简单方法是什么 我希
  • 在java中设置按钮点击延迟?

    我有一个保存按钮JFrame 单击 保存 时 保存 文本将设置为 正在保存 我需要在延迟 10 秒后将该文本设置为 已保存 在 java 中这怎么可能 请帮忙 try Thread sleep 4000 catch InterruptedE
  • 使用 Retrofit 2.0.x 进行 HTTP 缓存

    我正在尝试使用 Retrofit 2 0 在我的应用程序中缓存一些响应 但我遗漏了一些内容 我安装了一个缓存文件 如下 private static File httpCacheDir private static Cache cache