Tom Darious
Tom Darious

Reputation: 523

Retrofit SocketTimeoutException Error When API is Down

I'm trying to create an Interceptor in the event that the API I'm using goes down, which has happened when I tried to make an API call on Postman only for it to return a 504 error.

This is the OkHttpClient I have for now. I set it to 5 seconds only for testing purposes.

val client = OkHttpClient.Builder()
    .connectTimeout(5, TimeUnit.SECONDS)
    .writeTimeout(5, TimeUnit.SECONDS)
    .readTimeout(5, TimeUnit.SECONDS)
    .addInterceptor(object : Interceptor {
        override fun intercept(chain: Interceptor.Chain): okhttp3.Response  {
            val response = chain.proceed(chain.request())
            when (response.code()) {
                504 -> {
                    //Show Bad Request Error Message
                }
            }
            return response
        }
    })
    .build()

searchRetrofit = Retrofit.Builder()
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .baseUrl(URL)
    .client(client)
    .build()

Later in the code, I use Retrofit's execute() method to make a synchronous call to the API. The execute() line and val response = chain.proceed(chain.request()) crashes my app if the API service is down or if it's taking too long to retrieve results. I get the java.net.SocketTimeoutException error.

What can I do to prevent my app from crashing when the API service I'm using is down? What can I add to the Interceptor or should I surround my execute() call in a try catch statement?

Upvotes: 2

Views: 1202

Answers (1)

mightyWOZ
mightyWOZ

Reputation: 8355

Proper solution would be to use enqueue instead of execute. synchronous network calls are almost always a bad idea, because you don't want to block the calling thread. to use enqueue you should do

call.enqueue(object : Callback<SomeResponse> {
    override fun onFailure(call: Call<SomeResponse>?, t: Throwable?) {
        // This code will be called when your network call fails with some exception
        // SocketTimeOutException etc
    }

    override fun onResponse(call: Call<SomeResponse>?, response: Response<SomeResponse>?) {
        // This code will be called when response is received from network
        // response can be anything 200, 504 etc
    }
})

If you must use execute then at the very least you will have to enclose your execute call in try catch

try{
    call.execute()
}
catch(e: Exception){
     // Process any received exception (SocketTimeOutEtc)
}

Upvotes: 2

Related Questions