Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Retrofit with OKHttp use cache data when offline

I want to Retrofit with OkHttp uses cache when is no Internet.

I prepare OkHttpClient like this:

    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);
                }
            }
    });

and setting cache like this:

   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);
    }

and I checked on rooted device, that in cache directory are saving files with the "Response headers" and Gzip files.

But I don't get the correct answer from retrofit cache in offline, although in GZip file is coded my correct answer. So how can I make Retrofit can read GZip file and how can he know which file it should be (because I have a few files there with other responses) ?

like image 950
mac229 Avatar asked Jul 09 '15 15:07

mac229


People also ask

Does Retrofit cache data?

You cannot cache POST requests. Only GET requests can be cached. Inside the interceptors, you need to get chain. request() to get the current request and add Cache options to it.

Does Retrofit support caching?

In this blog, We are going to learn about how to achieve Retrofit Offline Caching in Android. We know that OkHttp is the default HttpClient for Retrofit. OkHttp comes with a powerful component Interceptors.

How does OkHttp caching work?

Basically: The client will send out something like timestamp or Etag of the last request. The server can then check if there is some data has changed in during that period of time or not. If nothing has changed, the server can just give a special code (304 -not modified) without sending the whole same response again.


1 Answers

I have simlar problem in my company :)

The problem was on server side. In serwer response i have:

Pragma: no-cache

So when i removed this everything starts working. Before i removed it i get all the time such exceptions: 504 Unsatisfiable Request (only-if-cached)

Ok so how implementation on my side looks.

    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);

If you have problems in testing on which side is problem (server or app). You can use such feauture to set headers received from server.

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();
    }
};

and simply add it:

okHttpClient.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);

Thanks to that as you can see i was able to remove Pragma: no-cache header for test time.

Also i suggest you to read about Cache-Control header:

max-age,max-stale

Other usefull links:

List of HTTP header fields

Cache controll

Another sample code

like image 178
Dawid Avatar answered Sep 21 '22 04:09

Dawid