Caching with OkHttp Interceptor and Retrofit
Tags: android
Published: 2022-09-15 11:43:28

---
title: Caching with OkHttp Interceptor and Retrofit
published: true
description: In this blog, we are going to learn how to cache HTTP responses in Android using OkHttp Interceptor and Retrofit for building offline-first Android apps.
tags: Android
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3xk96t4l12eyvbzywxld.png
canonical_url: https://amitshekhar.me/blog/caching-with-okhttp-interceptor-and-retrofit
---

I am [**Amit Shekhar**](https://amitshekhar.me), a mentor helping developers in getting high-paying tech jobs.

In this blog, we are going to learn how to cache HTTP responses in Android using OkHttp Interceptor and Retrofit for building offline-first Android apps.

**This article was originally published at [amitshekhar.me](https://amitshekhar.me/blog/caching-with-okhttp-interceptor-and-retrofit).**

Let's understand how caching is going to help us in our Android applications.

- When we make a network call to fetch the data from the server.
- For the very first time, it will get the data from the server and it will cache the HTTP response on the client.
- Then, if we make the same API call again, it will return the data from the cache instantly.

This way, our Android applications can do two very important things:

- Work even if there is **no internet connection**. This will helps us in building the **offline-first apps**.
- Work **faster** as the response is cached locally.

Now, let's learn how to enable caching in OkHttp and Retrofit. Before that, we need to understand that Retrofit uses the OkHttp client for HTTP operations, which means that whatever we have to do to enable caching, we need to do with the OkHttp. We do not have to do anything extra for Retrofit as it will use our configured OkHttp client.

Things become easier when we already have the `Cache-Control` header enabled from the server, then OkHttp will respect that header and cache the response for a specific time that is being sent from the server.

But what if the `Cache-Control` is not enabled from the server? We can still cache the response from OkHttp Client using Interceptor. We will learn how.

For this, we need to implement `Interceptor` like below:

```kotlin
class CacheInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val response: Response = chain.proceed(chain.request())
        val cacheControl = CacheControl.Builder()
            .maxAge(10, TimeUnit.DAYS)
            .build()
        return response.newBuilder()
            .header("Cache-Control", cacheControl.toString())
            .build()
    }
}
```

Here, we created `CacheInterceptor` by implementing `Interceptor` and we have a `CacheControl` builder that is used to provide the header for the `Cache-Control`.

Then, we need to add this `CacheInterceptor` to the `OkHttpClient` using `addNetworkInterceptor`.

```kotlin
val okHttpClient = OkHttpClient().newBuilder() 
.addNetworkInterceptor(CacheInterceptor())
.build();
```

After that, we can use this `okHttpClient` directly or with Retrofit.

But, there is a catch that we need to understand while building the offline-first app.

**OkHttp is designed in such a way that it returns the cached response only when the Internet is available.**

- It returns the data from the cache only when the Internet is available and the data is cached.
- It returns with the error "no internet available" even when the data is cached and but the Internet is not available.

**How to solve this issue?**

We can create a `ForceCacheInterceptor` in addition to the above one (`CacheInterceptor`, only if `Cache-Control` header is not enabled from the server).

```kotlin
class ForceCacheInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val builder: Request.Builder = chain.request().newBuilder()
        if (!IsInternetAvailable()) {
            builder.cacheControl(CacheControl.FORCE_CACHE);
        }
        return chain.proceed(builder.build());
    }
}
```

Then, add the interceptor in `OkHttpClient` like below:

```kotlin 
val okHttpClient = OkHttpClient().newBuilder()
.addNetworkInterceptor(CacheInterceptor()) // only if Cache-Control header is not enabled from the server
.addInterceptor(ForceCacheInterceptor())
.build();
```

Here, we need to notice that we are adding `ForceCacheInterceptor` to `OkHttpClient` using `addInterceptor()` and not `addNetworkInterceptor()`.

- `addInterceptor`: used to add the interceptor at the application level.
- `addNetworkInterceptor`: As the name says, used to add the interceptor at the network level.

After that, we can use this `okHttpClient` directly or with Retrofit and it will work as expected.

This is how we can cache HTTP responses in Android using OkHttp Interceptor and Retrofit for building offline-first Android apps.

That's it for now.

Thanks

[**Amit Shekhar**](https://amitshekhar.me)

You can connect with me on:

- [Twitter](https://twitter.com/amitiitbhu)
- [LinkedIn](https://www.linkedin.com/in/amit-shekhar-iitbhu)
- [GitHub](https://github.com/amitshekhariitbhu)
- [Facebook](https://www.facebook.com/amit.shekhar.iitbhu)