gpt4 book ai didi

android - 改造 + OkHTTP - 响应缓存不工作

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:39:31 24 4
gpt4 key购买 nike

我知道有很多类似的问题,但我已经阅读了所有这些问题,但没有一个真正有帮助。

所以,这是我的问题:

我正在使用 retrofit + okhttp 从 API 获取一些数据,我想缓存它们。不幸的是,我没有 API 服务器的管理员权限,所以我无法修改服务器返回的 header 。 (目前,服务器返回 Cache-control: private)

所以我决定使用 okhttp header 欺骗来插入适当的缓存 header 。可悲的是,无论我做什么,缓存似乎都不起作用。

我像这样初始化 api 服务:

int cacheSize = 10 * 1024 * 1024; // 10 MiB
File cacheFile = new File(context.getCacheDir(), "thumbs");
final Cache cache = new Cache(cacheFile, cacheSize);

OkHttpClient client = new OkHttpClient();
client.setCache(cache);
client.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.removeHeader("Access-Control-Allow-Origin")
.removeHeader("Vary")
.removeHeader("Age")
.removeHeader("Via")
.removeHeader("C3-Request")
.removeHeader("C3-Domain")
.removeHeader("C3-Date")
.removeHeader("C3-Hostname")
.removeHeader("C3-Cache-Control")
.removeHeader("X-Varnish-back")
.removeHeader("X-Varnish")
.removeHeader("X-Cache")
.removeHeader("X-Cache-Hit")
.removeHeader("X-Varnish-front")
.removeHeader("Connection")
.removeHeader("Accept-Ranges")
.removeHeader("Transfer-Encoding")
.header("Cache-Control", "public, max-age=60")
//.header("Expires", "Mon, 27 Apr 2015 08:15:14 GMT")
.build();
}
});

RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_ROOT)
.setLogLevel(RestAdapter.LogLevel.HEADERS_AND_ARGS)
.setClient(new OkClient(client))
.setConverter(new SimpleXMLConverter(false))
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
if (Network.isConnected(context)) {
int maxAge = 60; // read from cache for 2 minutes
request.addHeader("Cache-Control", "public, max-age=" + maxAge);
} else {
int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
request.addHeader("Cache-Control",
"public, only-if-cached, max-stale=" + maxStale);
}
}
})
.build();
api = restAdapter.create(ApiService.class);

当然,没有必要删除所有这些 header ,但我想让响应尽可能干净,以排除这些额外 header 的干扰。

如您所见,我还试图欺骗 Expires 和 Date header (我尝试删除它们,设置它们以便它们之间完全存在最大年龄差异,并将 Expires 设置为很远的 future )。我还尝试了各种 Cache-control 值,但没有成功。

我确保 cacheFile 存在,isDirectory 并且可由应用程序写入。

这些是改造后直接记录的请求和响应 header :

Request:
Cache-Control: public, max-age=60
---> END HTTP (no body)

Response:
Date: Mon, 27 Apr 2015 08:41:10 GMT
Server: Apache/2.2.22 (Ubuntu)
Expires: Mon, 27 Apr 2015 08:46:10 GMT
Content-Type: text/xml; charset=UTF-8
OkHttp-Selected-Protocol: http/1.1
OkHttp-Sent-Millis: 1430124070000
OkHttp-Received-Millis: 1430124070040
Cache-Control: public, max-age=60
<--- END HTTP (-1-byte body)
<--- BODY: ...

最后,还有一个奇怪的事件:在某个时刻,缓存工作了几分钟。我得到了合理的命中数,甚至离线请求也返回了缓存值。 (使用此处发布的确切设置时发生了这种情况)但是当我重新启动应用程序时,一切都恢复为“正常”(持续命中计数为 0)。

Co 如果有人知道这里可能是什么问题,我很乐意提供任何帮助:)

最佳答案

使用 networkInterceptors() 而不是 interceptors()。结合您删除与缓存有点相关的任何 header 的策略将起作用。这是简短的回答。

当您使用拦截器更改 header 时,它不会在调用 CacheStrategy.isCacheable() 之前进行任何调整。值得查看 CacheStrategy 和 CacheControl 类以了解 OKHttp 如何处理与缓存相关的 header 。在 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 上按 ctrl+f “缓存”也是值得的

我不确定 networkInterceptors() 和 interceptors() 文档是否不清楚或者是否存在错误。深入研究后,我将更新此答案。

关于android - 改造 + OkHTTP - 响应缓存不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29891139/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com