Can Retrofit with OKHttp Utilize Cached Data When Offline?
In an attempt to cache HTTP responses using Retrofit and OKHttp, you encountered the issue of obtaining a RetrofitError UnknownHostException when offline. This indicates that Retrofit is unable to retrieve cached data. The following modifications are necessary to resolve this issue:
Edit for Retrofit 2.x:
Implement an OkHttp Interceptor to manage caching logic:
<code class="java">private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Response originalResponse = chain.proceed(chain.request()); if (Utils.isNetworkAvailable(context)) { int maxAge = 60; // read from cache for 1 minute return originalResponse.newBuilder() .header("Cache-Control", "public, max-age=" + maxAge) .build(); } else { int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale return originalResponse.newBuilder() .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } } }</code>
Configure the OkHttpClient with the interceptor and cache:
<code class="java">OkHttpClient client = new OkHttpClient(); client.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR); //setup cache File httpCacheDirectory = new File(context.getCacheDir(), "responses"); int cacheSize = 10 * 1024 * 1024; // 10 MiB Cache cache = new Cache(httpCacheDirectory, cacheSize); //add cache to the client client.setCache(cache);</code>
Integrate the OkHttpClient with Retrofit:
<code class="java">Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build();</code>
OKHttp 2.0.x:
Adjust your client setup to reflect the updated syntax:
<code class="java"> File httpCacheDirectory = new File(context.getCacheDir(), "responses"); 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); } ...</code>
Original Answer:
Implement a request interceptor that sets the Cache-Control header based on network availability:
<code class="java">RestAdapter.Builder builder= new RestAdapter.Builder() .setRequestInterceptor(new RequestInterceptor() { @Override public void intercept(RequestFacade request) { request.addHeader("Accept", "application/json;versions=1"); if (MyApplicationUtils.isNetworkAvailable(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); } } });</code>
By implementing these modifications, Retrofit will correctly utilize cached data when offline, as long as the server response includes the appropriate Cache-Control headers.
The above is the detailed content of Can Retrofit with OKHttp Utilize Cached Data When Offline?. For more information, please follow other related articles on the PHP Chinese website!