Hi, I am Amit Shekhar, Co-Founder @ Outcome School • IIT 2010-14 • I have taught and mentored many developers, and their efforts landed them high-paying tech jobs, helped many tech companies in solving their unique problems, and created many open-source libraries being used by top companies. I am passionate about sharing knowledge through open-source, blogs, and videos.
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 Outcome School.
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:
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
.
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).
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:
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
Co-Founder @ Outcome School
You can connect with me on:
Top comments (1)
Thanks for your nice article. So how do we confirm that it has been retrieved from the cache?