【问题标题】:OKHTTP3 Offline cacheOKHTTP3 离线缓存
【发布时间】:2018-08-06 18:02:10
【问题描述】:

我想实现缓存,即使没有互联网连接(离线)但仍然没有成功,已经看了很多例子但仍然没有运气

//FeedInterceptor Class 
public static Interceptor getOfflineInterceptor(final Context context){
    Interceptor interceptor = new Interceptor() {
        @Override
        public okhttp3.Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            if (!isNetworkAvailable(context)) {
                request = request.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", "public, only-if-cached")
                        .build();
            }
            return chain.proceed(request);
        }
    };

    return interceptor;
}


//OnCreate Activity
client = new OkHttpClient.Builder()
            .addNetworkInterceptor(FeedInterceptor.getOnlineInterceptor(this))
            .addInterceptor(FeedInterceptor.getOfflineInterceptor(this))
            .cache(cache)
            .build();

//After build Request
Response response = client.newCall(request).execute();
return response.body().string();

如果离线,则返回为空字符串。 有什么我想念或错的吗?

【问题讨论】:

    标签: android caching okhttp3


    【解决方案1】:

    为了能够重用缓存的响应,响应本身必须通过提供一些标头(例如,Cache-Control: publicCache-Control: max-age=3600)来声明自己是“可缓存的”。您是否检查过您的回复是否包含此类标头?

    另外,考虑使用内置常量CacheControl.FORCE_CACHE 作为cacheControl setter 的值。

    最后,请注意(引自OkHttp documentation):

    注意:如果你使用FORCE_CACHE并且响应需要网络,OkHttp将返回一个504 Unsatisfiable Request响应

    编辑:

    这是一个完整的例子。

    final CacheControl cacheControl = new CacheControl.Builder()
            .maxAge(60, TimeUnit.MINUTES)
            .build();
    
    // Interceptor to ask for cached only responses
    Interceptor cacheResponseInterceptor = chain -> {
        Response response = chain.proceed(chain.request());
        return response.newBuilder()
                .header("Cache-Control", cacheControl.toString())
                .build();
    };
    
    // Interceptor to cache responses
    Interceptor cacheRequestInterceptor = chain -> {
        Request request = chain.request();
        request = request.newBuilder()
                .cacheControl(CacheControl.FORCE_CACHE)
                .build();
    
        return chain.proceed(request);
    };
    
    // Create a directory to cache responses. Max size = 10 MiB
    Cache cache = new Cache(new File("okhttp.cache"), 10 * 1024 * 1024);
    
    /*
     * Let's create the client. At the beginning the cache will be empty, so we will
     * add the interceptor for the request only after, for the 2nd call
     */
    OkHttpClient client = new OkHttpClient.Builder()
            .cache(cache)
            .addNetworkInterceptor(cacheResponseInterceptor)
            .build();
    
    // Let's do the call
    Request request = new Request.Builder()
            .url("http://httpbin.org/get")
            .get()
            .build();
    Response response = client.newCall(request).execute();
    response.close();
    
    // Let's add the interceptor for the request
    client = client.newBuilder()
            .addInterceptor(cacheRequestInterceptor)
            .build();
    
    // Let's do the same call
    request = new Request.Builder()
            .url("http://httpbin.org/get")
            .get()
            .build();
    response = client.newCall(request).execute();
    response.close();
    
    // Let's see if we had some issues with the cache
    System.out.println("Is successful? " + response.isSuccessful());
    

    请注意,由于这是一个“独立”示例,我必须进行 2 次调用:

    1. 此调用使用网络获取对缓存的有效响应,否则我的缓存将为空。在您的情况下,您不需要它,因为通常您会使用设备数据进行“真实”调用;请注意,这里我使用了网络拦截器,它添加了标头“好的,您可以缓存此响应”。
    2. 我添加了强制使用缓存的拦截器。这里不会使用网络拦截器,因为要么在缓存中找到响应,要么返回 504 响应。

    另请注意,您需要关闭响应,否则缓存将无法正确填充。

    【讨论】:

    • 是的,响应没有任何缓存控制,有什么解决办法吗?
    • 您可以利用Interceptor 机制在响应中手动注入其中一个标头。为此,您获取chain.proceed(request) 返回的Response,您将获得一个新的构建器并注入您需要的标头。这与您对Request 所做的非常相似。最后,您返回新创建的Response,您应该可以从缓存中受益
    • 卡在添加标头,你的意思是在 Response response = client.newCall(request).execute();或制作新的拦截器?之前添加了 response = response.newBuilder() 和与 Interceptor 相同的标头,但仍然有 504
    • @SeptianTriadi 我添加了一个工作示例来向您展示应该如何完成
    • 还有很多事情要做。我试过后会回复的。谢谢!
    猜你喜欢
    • 2017-04-29
    • 2018-03-28
    • 2010-11-15
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 2016-12-16
    • 1970-01-01
    相关资源
    最近更新 更多