离线时使用 OKHttp 进行改造如何使用缓存数据

Posted

技术标签:

【中文标题】离线时使用 OKHttp 进行改造如何使用缓存数据【英文标题】:How Retrofit with OKHttp use cache data when offline 【发布时间】:2015-09-28 02:13:39 【问题描述】:

我想用 OkHttp 进行改造,在没有互联网的情况下使用缓存。

我这样准备 OkHttpClient:

    RestAdapter.Builder builder= new RestAdapter.Builder()
       .setRequestInterceptor(new RequestInterceptor() 
            @Override
            public void intercept(RequestFacade request) 
                request.addHeader("Accept", "application/json;versions=1");
                if (MyApplicationUtils.isNetworkAvaliable(context)) 
                    int maxAge = 60; // read from cache for 1 minute
                    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);
                
            
    );

并像这样设置缓存:

   Cache cache = null;
    try 
        cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024);
     catch (IOException e) 
        Log.e("OKHttp", "Could not create http cache", e);
    

    OkHttpClient okHttpClient = new OkHttpClient();
    if (cache != null) 
        okHttpClient.setCache(cache);
    

我检查了根设备,缓存目录中正在保存带有“响应头”和 Gzip 文件的文件。

但我没有从离线改造缓存中得到正确答案,尽管在 GZip 文件中编码了我的正确答案。那么我怎样才能让 Retrofit 可以读取 GZip 文件,他怎么知道它应该是哪个文件(因为我有几个文件有其他响应)?

【问题讨论】:

【参考方案1】:

我的公司也有类似的问题:)

问题出在服务器端。在服务器响应中,我有:

Pragma: no-cache

所以当我删除它时,一切都开始工作了。在我删除它之前,我总是遇到这样的异常:504 Unsatisfiable Request (only-if-cached)

好的,我这边的实现看起来如何。

    OkHttpClient okHttpClient = new OkHttpClient();

    File httpCacheDirectory = new File(appContext.getCacheDir(), "responses");

    Cache cache = new Cache(httpCacheDirectory, maxSizeInBytes);
    okHttpClient.setCache(cache);

    OkClient okClient = new OkClient(okHttpClient);

    RestAdapter.Builder builder = new RestAdapter.Builder();
    builder.setEndpoint(endpoint);
    builder.setClient(okClient);

如果您在测试哪一方有问题(服务器或应用程序)时遇到问题。您可以使用此类功能设置从服务器接收的标头。

private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() 
    @Override
    public Response intercept(Chain chain) throws IOException 
        Response originalResponse = chain.proceed(chain.request());
        return originalResponse.newBuilder()
                               .removeHeader("Pragma")
                               .header("Cache-Control",
                                       String.format("max-age=%d", 60))
                               .build();
    
;

然后简单地添加它:

okHttpClient.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);

多亏了这一点,正如您所见,我能够在测试时间删除 Pragma: no-cache 标头。

另外我建议你阅读Cache-Control header:

max-age,max-stale

其他有用的链接:

List of HTTP header fields

Cache controll

Another sample code

【讨论】:

你就是男人!您不仅节省了我的时间,还节省了两天时间:D.

以上是关于离线时使用 OKHttp 进行改造如何使用缓存数据的主要内容,如果未能解决你的问题,请参考以下文章

改造 OKHTTP 离线缓存不起作用

使用 OkHttp 缓存 POST 请求

即使在离线时如何缓存网页以在我的 android 应用程序中使用

使用OkHttp拦截器和Retrofit进行缓存

使用OkHttp拦截器和Retrofit进行缓存

Android Webview离线时加载缓存