Android rxJava Manejo de errores con retroadaptación
Estoy utilizando el nuevo RX java en lugar de
Observable.create(new Observable.OnSubscribeFunc<T>() {...});
Esto se utiliza: (debido a la depreciación)
- RxJava: "java.lang.IllegalStateException: Sólo un suscriptor permitido!"
- RxJava2 función de rebote no funciona correctamente en RecyclerView - Android
- RxBindings para Spinner?
- Encadenamiento de RxJava observables con callbacks / listeners
- ¿Cómo se muestra spinner si RxJava observable toma mucho tiempo?
Observable.create(new Observable.OnSubscribe<T>() {...});
(Esto puede ser importante ya que la mayoría de ejemplos, tutoriales, explonación usan el antiguo …)
Bueno, veamos mi problema. Tengo una clase de Java, partes relevantes de ella:
private interface ApiManagerService { @FormUrlEncoded @POST("/login") User getUser(@Field("username") String userName, @Field("password") String password); } private static RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(HOST) .setLogLevel(RestAdapter.LogLevel.FULL) .build(); private static ApiManagerService apiManager = restAdapter.create(ApiManagerService.class); public static Subscription login(final String userName, final String password, Observer<User> observer) { return Observable.create(new Observable.OnSubscribe<User>() { @Override public void call(Subscriber<? super User> subscriber) { try { User user = apiManager.getUser(userName, password); subscriber.onNext(user); subscriber.onCompleted(); } catch (RetrofitError e) { subscriber.onError(e); } catch (Throwable e) { subscriber.onError(e); } } } ).subscribeOn(Schedulers.io()) .retry(3) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer); }
Este código casi funciona perfectamente, si todo está bien. Pero si hago un error intencional, al igual que apagar el WiFi .. que retrofit obtener el "UnKnownHostException" … como debería suceder en la llamada de retrofit (getUser) en el bloque try catch. Pero en lugar de manejar el error a onError (Throwable t) -> donde podría manejar, simplemente bloquea la aplicación. Por lo tanto, es como si el error nunca llega al bloque catch. Lo que es extraño que los errores HTTP (como 404, 401, etc) es atrapado, recibió onError (…) y todo está bien.
Todo va por 3 veces antes del accidente, como de .retry (3) pero ninguno entra en la cláusula catch.
EDITAR 1
LogCat Salida:
01-08 16:19:31.576 15285-16162/asd.bdef.gh D/Retrofit﹕ ---- ERROR https://testapi.com/api/login 01-08 16:19:31.606 15285-16162/asd.bdef.gh D/Retrofit﹕ java.net.UnknownHostException: Unable to resolve host "testapi.com": No address associated with hostname at java.net.InetAddress.lookupHostByName(InetAddress.java:394) at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236) at java.net.InetAddress.getAllByName(InetAddress.java:214) at com.squareup.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29) at com.squareup.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:259) at com.squareup.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:233) at com.squareup.okhttp.internal.http.RouteSelector.nextUnconnected(RouteSelector.java:159) at com.squareup.okhttp.internal.http.RouteSelector.next(RouteSelector.java:133) at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:314) at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:237) at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:423) at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:105) at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:239) at com.squareup.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218) at com.squareup.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:25) at retrofit.client.UrlConnectionClient.prepareRequest(UrlConnectionClient.java:68) at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:37) at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:321) at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220) at retrofit.RestAdapter$RestHandler$1.invoke(RestAdapter.java:265) at retrofit.RxSupport$2.run(RxSupport.java:55) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390) at java.util.concurrent.FutureTask.run(FutureTask.java:234) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) at retrofit.Platform$Android$2$1.run(Platform.java:142) at java.lang.Thread.run(Thread.java:841) 01-08 16:19:31.606 15285-16162/asd.bdef.gh D/Retrofit﹕ ---- END ERROR 01-08 16:19:31.977 15285-15285/asd.bdef.gh D/AndroidRuntime﹕ Shutting down VM 01-08 16:19:31.977 15285-15285/asd.bdef.gh W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41c9d8b0) 01-08 16:19:31.977 15285-15285/asd.bdef.gh E/AndroidRuntime﹕ FATAL EXCEPTION: main
La dirección de api dada no es la verdadera, pero la real es accesible. Acabo de apagar el WiFi para probar el manejo de errores.
Y un caso de uso más: Si agrego a la observable .onExceptionResumeNext ([2nd observable]) que va a la segunda observable, y no se bloquea. Pero esta no es la solución del problema.
EDIT 2
ApiManager.login(userName, pass, new Observer<User>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { DialogManager.showBasicErrorDialog(getApplicationContext(), e.getLocalizedMessage()); logger.showLog("Login Not ok"); e.printStackTrace(); } @Override public void onNext(User user) { logger.showLog("login ok, user: " + user.getName().toString()); {...} } });
EDIT 3
FATAL EXCEPTION: main rx.exceptions.OnErrorFailedException: Error occurred when trying to propagate error to Observer.onError at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:175) at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:97) at rx.internal.operators.NotificationLite.accept(NotificationLite.java:144)
{…}
Caused by: java.lang.NullPointerException: Attempt to read from field 'rx.functions.Action0 rx.schedulers.TrampolineScheduler$TimedAction.action' on a null object reference at rx.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:85)
Gracias de antemano por ayudar.
- Excepción fatal lanzada en el subprograma Scheduler.Worker con Retrofit 2 y Rx
- Retorno combinado observable sólo si una condición coincide
- Manejo de excepciones API en RxJava
- RxJava No puede crear el controlador dentro de hilo que no ha llamado Looper.prepare ()
- IllegalArgumentException: No se pudo localizar el adaptador de llamada para rx.Observable RxJava, Retrofit2
- Acceso al dominio desde un subproceso incorrecto Excepción mientras se envió una copia usando copyFromRealm
- RxJava / Retrofit - ¿Cómo puedo obligar a los usuarios a usar una subclase específica de suscriptor?
- Usando observeOn () el hilo de interfaz de usuario de Android bloquea mi prueba de emulador
Parece que usted puede estar corriendo en un problema se ha fijado como de RxJava 1.0:
TrampolineScheduler NullPointerException
Usted no tiene que construir su propio Observable con Retrofit, como Retrofit puede devolver directamente Observable:
http://square.github.io/retrofit/
Retrofit también integra RxJava para soportar métodos con un tipo de retorno de rx.Observable
@GET ("/ user / {id} / photo") Observable getUserPhoto (@Path ("id") int id);
(Usted no tendrá que manejar errores por usted mismo)
¿Puedes publicar el stacktrace de tu accidente? Como pienso como usted, que su aplicación no se bloquee.
- ¿Por qué onLoadFinished se llama de nuevo después de que se reanude el fragmento?
- Google Place API para espacios de estacionamiento