android - method - Retrofit y OkHttpClient, capturan el tiempo de espera de conexión en el método de falla
retrofit and okhttpclient catch connection timeout in failure method (4)
Tengo la siguiente configuración:
final OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(5, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(5, TimeUnit.SECONDS);
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(ROOT)
.setClient(new OkClient(okHttpClient))
.setLogLevel(RestAdapter.LogLevel.FULL);
Estoy tratando de manejar la situación en la que mi servidor está inactivo y el usuario obtiene una excepción de tiempo de espera de conexión, este es mi registro:
java.net.SocketTimeoutException: failed to connect to /192.168.0.53 (port 3000) after 5000ms
Registro completo: http://pastebin.com/gscCGb7x
¿Hay alguna manera de encaminar esto en el método de falla de actualización para que pueda manejarlo allí?
¡Gracias por adelantado!
Aparentemente, la excepción se envuelve en una RetrofitException para que pueda manejarla en el método de falla.
Es un poco más complicado. Con Retrofit puede hacer llamadas API que son síncronas o asíncronas.
Si su punto final devuelve vacío y tiene una devolución de llamada, es asíncrono. Si devuelve algo y no tiene devolución de llamada, es sincrónico.
Para las llamadas asincrónicas, obtiene esta excepción en el
onFailure(...)
de su devolución de llamada.
Para las llamadas síncronas, no lo recibe en absoluto, a menos que finalice su llamada en un intento / captura.
try {
// your synchronous call goes here
} catch (RetrofitError error) {
// handle errors
}
Actualización: la respuesta anterior se aplica a Retrofit 1.9. Retrofit 2.0 ha cambiado esto mucho. Si se pregunta cómo funcionan las cosas ahora en Retrofit 2.0, este artículo le da algunos consejos http://inthecheesefactory.com/blog/retrofit-2.0/en
Para la actualización 2
Defina un oyente en su instancia de servicio web:
public interface OnConnectionTimeoutListener {
void onConnectionTimeout();
}
Agregue un interceptor a su servicio web:
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);
}
Incluya su código de intercepción con el bloque try-catch y notifique al oyente cuando ocurra una excepción:
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());
}
Kotlin
Si desea utilizar
Retrofit
en
Kotlin
siga los pasos a continuación:
Defina su interfaz de actualización:
interface GitHubApi {
@GET("/users/{userName}/repos")
fun repos(@Path("userName") userName: String): Call<List<Repo>>
}
Implemente su servicio:
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)
}
}
}
}
}
Llame a su servicio donde desee:
Api().repos("olcayertas",
onSuccess = {
Log.d("MainActivity", "Response:/n" + toJson(it))
},
onFailure = {
Log.e("MainActivity", "Error: $it")
})
Puede manejar cualquier excepción que desee en la función
runAsync
.
Puede obtener un ejemplo completamente funcional here .
@Override
public void onFailure(Call call, Throwable t) {
if(t instanceof SocketTimeoutException){
message = "Socket Time out. Please try again.";
}
}