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)

 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.

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.

  • Android: Sondeo de un servidor con Retrofit
  • AbstractMethodError cuando se utiliza RxJavaCallAdapterFactory en Retrofit 2
  • RxAndroid: cambios de interfaz de usuario en el subproceso Schedulers.io ()
  • Actualización de datos mediante SQLBrite + Retrofit
  • RxJava alternativa para el operador map () para guardar los elementos emitidos
  • RxJava Break Chain en Condicional
  • Robolectric Test no llama a textWatcher.onTextChanged
  • ¿Cómo terminar un observable?
  • La comprensión incorrecta del búfer en RxJava
  • Comprobación de Internet, dónde colocar al usar MVP, RX y Retrofit
  • Manera correcta de manejar ninguna red con Retrofit y RX-java
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.