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) ?
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With