I have the following setup:
final OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(5, TimeUnit.SECONDS);
okHttpClient.setConnectTi
It's a bit more complicated. With Retrofit you can make API calls that are either synchronous or asynchronous.
If your endpoint returns void and has a callback it is asynchronous. If it returns something and has no callback it's synchronous.
For asynchronous calls you get this exception in the onFailure(...)
method of your callback.
For synchronous calls you don't get it at all, unless you wrap your call in a try/catch.
try {
// your synchronous call goes here
} catch (RetrofitError error) {
// handle errors
}
Update: The above answer applies to Retrofit 1.9. Retrofit 2.0 has changed this a lot. If you're wondering about how things now work in Retrofit 2.0, this article gives some pointers http://inthecheesefactory.com/blog/retrofit-2.0/en
Apparently the exception does get wrapped into a RetrofitException so you can handle it in the failure method.
For Retrofit 2
Define a listener in your web service instance:
public interface OnConnectionTimeoutListener {
void onConnectionTimeout();
}
Add an interceptor to your web service:
public WebServiceClient() {
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(10, TimeUnit.SECONDS);
client.setReadTimeout(30, TimeUnit.SECONDS);
client.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
return onOnIntercept(chain);
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
webService = retrofit.create(WebService.class);
}
Enclose your intercep code with try-catch block and notify listener when exception happens:
private Response onOnIntercept(Chain chain) throws IOException {
try {
Response response = chain.proceed(chain.request());
String content = UtilityMethods.convertResponseToString(response);
Log.d(TAG, lastCalledMethodName + " - " + content);
return response.newBuilder().body(ResponseBody.create(response.body().contentType(), content)).build();
}
catch (SocketTimeoutException exception) {
exception.printStackTrace();
if(listener != null)
listener.onConnectionTimeout();
}
return chain.proceed(chain.request());
}
@Override
public void onFailure(Call call, Throwable t) {
if(t instanceof SocketTimeoutException){
message = "Socket Time out. Please try again.";
}
}
In case someone come here with Kotlin/Coroutines facing the same issue, add an error handler to your coroutines scope:
CoroutineScope(Dispatchers.IO).launch(handler) {
while the handler by itself looks like:
val handler = CoroutineExceptionHandler { _, exception ->
Log.t("Network", "Caught $exception")
}
Kotlin
If you want to use Retrofit
in Kotlin
follow below steps:
Define your Retrofit interface:
interface GitHubApi {
@GET("/users/{userName}/repos")
fun repos(@Path("userName") userName: String): Call<List<Repo>>
}
Implement your service:
class Api(...) {
private val baseUrl = "https://api.github.com"
private val api: GitHubApi
private fun loggingInterceptor(...): HttpLoggingInterceptor {...}
private fun okHttpBuilder(): OkHttpClient {...}
init {...}
fun repos(
userName: String,
onSuccess: (list: List<Repo>?) -> Unit,
onFailure: (message: String?) -> Unit): Future<Unit> {
return runAsync(api.repos(userName), onSuccess, onFailure)
}
private fun <T> runAsync(
call: retrofit2.Call<T>,
onSuccess: (T?) -> Unit,
onFailure: (message: String?) -> Unit) : Future<Unit> {
return doAsync {
try {
val response = call.execute()
when {
response.isSuccessful -> response.body()?.let {
onSuccess(it)
}
else -> {
onFailure(response.raw().message())
}
}
} catch (e: IOException) {
if (e is SocketTimeoutException) {
onFailure("Response time out!")
} else {
onFailure(e.message)
}
}
}
}
}
Call your service in where you want:
Api().repos("olcayertas",
onSuccess = {
Log.d("MainActivity", "Response:\n" + toJson(it))
},
onFailure = {
Log.e("MainActivity", "Error: $it")
})
You can handle any exception you want in runAsync
function.
You can get fully working example here.