我正在尝试使用Retrofit和OKHttp来缓存HTTP响应 . 我跟着this gist,最后得到了这段代码:
File httpCacheDirectory = new File(context.getCacheDir(), "responses");
HttpResponseCache httpResponseCache = null;
try {
httpResponseCache = new HttpResponseCache(httpCacheDirectory, 10 * 1024 * 1024);
} catch (IOException e) {
Log.e("Retrofit", "Could not create http cache", e);
}
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setResponseCache(httpResponseCache);
api = new RestAdapter.Builder()
.setEndpoint(API_URL)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient(okHttpClient))
.build()
.create(MyApi.class);
这是带有Cache-Control标头的MyApi
public interface MyApi {
@Headers("Cache-Control: public, max-age=640000, s-maxage=640000 , max-stale=2419200")
@GET("/api/v1/person/1/")
void requestPerson(
Callback<Person> callback
);
首先,我在线请求并检查缓存文件 . 有正确的JSON响应和 Headers . 但是当我尝试离线请求时,我总是得到 RetrofitError UnknownHostException
. 我还有什么办法让Retrofit从缓存中读取响应吗?
EDIT: 由于OKHttp 2.0.x HttpResponseCache
是 Cache
, setResponseCache
是 setCache
6 回答
编辑改造2.x:
OkHttp Interceptor是离线时访问缓存的正确方法:
1)创建拦截器:
2)设置客户端:
3)添加客户端进行改造
另请查看 @kosiara - Bartosz Kosarzycki 的answer . 您可能需要从响应中删除一些标头 .
OKHttp 2.0.x(查看原始答案):
由于OKHttp 2.0.x
HttpResponseCache
是Cache
,setResponseCache
是setCache
. 所以你应该setCache
这样:原文答案:
事实证明,服务器响应必须
Cache-Control: public
才能使OkClient
从缓存中读取 .此外,如果要在可用时从网络请求,则应添加
Cache-Control: max-age=0
请求标头 . This answer显示了如何进行参数化 . 这就是我使用它的方式:以上所有的东西都不适合我 . 我试图在 retrofit 2.0.0-beta2 中实现离线缓存 . 我使用
okHttpClient.networkInterceptors()
方法添加了一个拦截器,但是当我尝试脱机使用缓存时收到java.net.UnknownHostException
. 事实证明我也必须添加okHttpClient.interceptors()
.问题是缓存没有写入闪存存储,因为服务器返回了
Pragma:no-cache
,这阻止了OkHttp存储响应 . 即使在修改请求标头值后,脱机缓存也不起作用 . 经过一些试验和错误后,我通过从响应中删除pragma而不是请求来使缓存工作而不修改后端端 -response.newBuilder().removeHeader("Pragma");
改造: 2.0.0-beta2 ; OkHttp: 2.5.0
...
...
我的解决方案
Build 在@ kosiara-bartosz-kasarzycki的answer上,我创建了一个示例项目,使用改造,okhttp,rxjava和guava从内存 - >磁盘 - >网络正确加载 . https://github.com/digitalbuddha/StoreDemo
答案是肯定的,根据上述答案,我开始编写单元测试来验证所有可能的用例:
Use cache when offline
首先使用缓存响应,直到过期,然后使用网络
首先使用网络然后缓存某些请求
不要在缓存中存储某些响应
我构建了一个小助手lib来轻松配置OKHttp缓存,你可以在Github上看到相关的单元测试:https://github.com/ncornette/OkCacheControl/blob/master/okcache-control/src/test/java/com/ncornette/cache/OkCacheControlTest.java
单元测试,演示离线时使用缓存:
如您所见,即使缓存已过期,也可以使用缓存 . 希望它会有所帮助 .
使用Retrofit2和OkHTTP3缓存:
NetworkUtils.isNetworkAvailable()静态方法:
然后只需将客户端添加到改造构建器:
原始来源:https://newfivefour.com/android-retrofit2-okhttp3-cache-network-request-offline.html