Android rxJava使用改造进行error handling

我正在使用较新的RX java而不是

Observable.create(new Observable.OnSubscribeFunc() {...}); 

使用:(由于弃用)

 Observable.create(new Observable.OnSubscribe() {...}); 

(这可能很重要,因为大多数示例,教程,explonation使用旧的……)

好吧,让我们看看我的问题。 我有一个Java类,它的相关部分:

 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 observer) { return Observable.create(new Observable.OnSubscribe() { @Override public void call(Subscriber 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); } 

如果一切正常,这段代码几乎可以完美运行。 但是,如果我发出故意错误,就像我关闭WiFi ..比改装得到“UnKnownHostException” ……因为它应该发生在try catch块中的改装调用(getUser)。 但是不是将error handling到onError(Throwable t) – >我可以处理的地方,它只会崩溃应用程序。 所以就好像错误永远不会到达catch块。 有什么奇怪的HTTP错误(如404,401等)被捕获,由onError(…)得到,一切都很好。

在崩溃之前一切都进行了3次,从.retry(3)开始,但没有一个进入catch子句。

编辑1

LogCat输出:

  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 

给定的api地址不是真实的,但真实的地址是可达的。 我刚关闭WiFi来测试error handling。

还有一个用例:如果我添加到observable .onExceptionResumeNext([2nd observable])而不是第二个observable,它就不会崩溃。 但这不是问题的解决方案。

编辑2

 ApiManager.login(userName, pass, new Observer() { @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()); {...} } }); 

编辑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) 

在此先感谢您的帮助。

从RxJava 1.0开始,看起来您可能遇到了一个问题:

TrampolineScheduler NullPointerException

您不必使用Retrofit构建自己的Observable,因为Retrofit可以直接返回Observable:

http://square.github.io/retrofit/

Retrofit还集成了RxJava,以支持返回types为rx.Observable的方法

@GET(“/ user / {id} / photo”)Observable getUserPhoto(@Path(“id”)int id);

(您不必自己处理错误)

你可以发布崩溃的堆栈跟踪吗? 正如我想的那样,您的应用程序不应该崩溃。