Explain Codes LogoExplain Codes Logo

Can Retrofit with OKHttp use cache data when offline

java
cache-control
offline-caching
retrofit-okhttp
Nikita BarsukovbyNikita Barsukov·Jan 31, 2025
TLDR

Implement offline caching in Retrofit with OkHttp by adding a Cache to the OkHttpClient. Set up CacheControl in requests to resort to cache data when offline.

// Set up the cache. Cache is like your offline library. Cache cache = new Cache(new File("cache-directory"), 10 * 1024 * 1024); // 10 MB // Set up the OkHttpClient with cache and interceptors, like a librarian managing books. OkHttpClient okHttpClient = new OkHttpClient.Builder() .addNetworkInterceptor(new Interceptor() { @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request request = chain.request(); // Here's the magic, if no network, let's go to the library. if (!isNetworkAvailable()) { int maxStale = 60 * 60 * 24 * 28; // 4 weeks request = request.newBuilder() .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } return chain.proceed(request); } }).cache(cache).build(); // Retrofit builder with OkHttpClient, basically building the library. Retrofit retrofit = new Retrofit.Builder() .client(okHttpClient) .baseUrl("http://your.api/") .build(); // Request with cache control like checking out a book from the library. Request request = new Request.Builder() .url("http://your.api/endpoint") .cacheControl(new CacheControl.Builder() .onlyIfCached() .maxStale(365, TimeUnit.DAYS) .build()) .build();

When the cache runs dry and there’s no network, you can handle this by catching the IOException.

Configuring caching

Offline caching with Retrofit and OkHttp comprises two main elements:

  • Network Interceptor: Sort of a gatekeeper for response, it ensures responses are cacheable (Cache-Control: public) and tweaks headers for optimal caching.
  • Application Interceptor: This handles cache use based on network availability. When offline, it resorts to cached data and fetches fresh data when online- appending Cache-Control: max-age=0 to validate cache.

Streamline your cache handling using Application Interceptor while maintaining control over how cache responses are delivered without Cache-Control headers.

Preparing for offline scenarios

Ensuring sound offline capabilities with Retrofit requires smart handling around potential pitfalls, such as falling back when lacking cache data. This can be achieved through an offline interceptor to mitigate no-host cases (UnknownHostException).

Organize your caching logic in separate methods that can be maintained easily. Carefully validate the cache's JSON and headers in the cache files for some quick debugging.

Efficient Cache Control

Here are some handy tips for efficient cache control:

  • Define a reasonable cache limit: Adjust your cache size based on your app's requirement, balancing memory used versus data needed.
  • Customize stale tolerance: Leverage max-stale headers when necessary to deliver older data when fresh data can't be fetched.
  • Clear cache periodically: Prevent accumulation of stale cache to avoid outdated responses.

Integration with RxJava and Guava

For a more reactive style of caching, Retrofit can be used with these libraries:

  • RxJava: This can be used along with Retrofit calls to manage cache actions in a straightforward flow.
  • Guava: Use Guava's sophisticated Cache mechanism for more advanced cache control.

Error handling and testing

Have strong error handling for offline scenarios to address situations when cache data is unavailable. Adding unit tests on cache actions ensures that the features work reliably in both online and offline situations.

Keeping Retrofit and OkHttp versions in check

Ensure your Retrofit and OkHttp versions are compatible to avoid any potential conflicts or unexpected behaviour in caching.