Advanced Retrofit2 (Part 1): Network Error Handling & Response Caching

Retrofit, most popular networking library in the recent times. The convenient thing I found in retrofit is the modularity with it’s components. It is highly customizable based on the requirement and use cases.

App uses Restful APIs to show up the content. Every activity/fragment/action may have require single/multiple API call to display/manipulate data that are keep stored in backend database. Every interaction requires network connectivity to be accomplished. Developers need to show error messages on the screen when network error occurs. Good apps cache the API response to show up the recent content when it’s running out of internet or slow in connection.

Before diving into the points of concern I would like to setup the code skeleton for this article.

Gradle dependencies for Retrofit and OkHttp
basic OkHttp configuration for Retrofit
API interface method for Retrofit

This is the basic setup/configuration of OkHttp3 as a Http client for Retrofit.
Now let’s jump to the point.

My first concern is how we should handle network error? Developer’s common practice is to have a network check before each and every API call which creates boilerplate and branching in the code. I was looking for an optimal solution. Finally come up with a solution by adding an Interceptor into okhttpClientBuilder.

Interceptor Observes, modifies, and potentially short-circuits requests going out and the corresponding responses coming back in. Typically interceptors add, remove, or transform headers on the request or response.

Let’s progress step by step. Firstly we will create a class named NetworkConnectionInterceptor and put an internet availability check inside the intercept(Chain chain) method.

Centralized check for network connection through out the app

Now lets, initialize an object of NetworkConnectionInterceptor and add this into okHttpClientBuilder. Before that we will create a simple interface InternetConnectionListener that will be used to pass the event to the listener (i.e: HomeActivity)

Simple interface to pass event to it’s listener
Initialization of NetworkConnectionInterceptor

Now we have our own NetworkConnectionInterceptor that checks for internet availability on each API call. We will have to implement InternetConnectionListener into our views (i.e: HomeActivity). If HomeActivity is a tabbed activity with ViewPager + Fragment and if the fragments are having there own API calls, in that case we don’t need to keep checking for internet connection before the API calls. When offline, the HomeActivity onInternetUnavailable will be get called. We can show up the no internet UI which we can place on the top of the ViewPager so that the content UI get invisible by the no internet UI. We can broadcast this event wherever we want by using LocalBroadcastReceiver/ RxBus/EventBus.

HomeActivity with a retrofit API call and InternetConnectionListener implementation.

Full code for App file looks like:

App class includes full code

By this way, we will have only a single check for internet connection and we can pass the event through out the app if there is no internet. We don’t need to handle the network check place to place. Rather, in case of no internet, interface method will get called to show up the error view.

My second concern is related to response caching that rises following questions:

How can we on/off cache usage depending on network condition? What to do if we don’t want to use cache when network is available?

How to set a time limit to validate cache data if we don’t want to show up content that is older than the time frame?

Let’s have the solution step by step.

Firstly we need to implement basic cache mechanism

Cache initialization for OkHttp

Now we have 10 MB of cache memory available thatOkHttp can use to read/write API response. We can increase/decrease the memory size depending on the payload size of response. Now OkHttp will keep caching all the response into the disk space. Let’s modify NetworkConnectionInterceptor to handle the response with cache in terms of network state.

NetworkConnectionInterceptor with cache handling mechanism (final)

Here we are manipulating the ongoing request when device is offline. We are doing nothing if there is internet available. We are modifying the request only when there is no internet. The idea is, we keep caching all the response of the request that are originated by OkHttp. But we are not pulling up the response when connected. When offline, we are adding some header information which returns the cache in offline mode. We are using max-stale= 60 * 60 * 24 that means, we are allowing the response that is cached within the past 24 Hours from now. If the cache is older than the specified time, OkHttp not gonna use it. More about only-if-cached and max-stale is here.

Wow! Now we have a cache functionality that response without an internet connection! Internet unavailability no longer means there is no content to show up. But content will be unavailable when there is no cache available (i.e: user open the app for the first time without internet or open the app after a long time when cache data become invalidate). That’s why we need a check if there is cache available for the request. And here we go, we are calling onCacheUnavailable() if response.cacheResponse() is null.

InternetConnectionListener with onCacheUnavailable()
App class full code with complete impl. of NetworkConnectionInterceptor
HomeActivity full code

That’s it! We can easily manage stateful behavior with a simple OkHttp Interceptor . We have callback for no internet and as well as no cache event. Our app can behave differently with these callback feature. We can manage behavior for a specific error response (i.e: when 401 Unauthorized/403 Forbidden occurs). I will come up with some short trick for this in later part.

Good user experience is the first priority!

Happy Coding!

Like what you read? Give Tushar Saha a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.