2015-01-08 146 views
11

我使用的是較新的RX java的地方,而不是的Android rxJava錯誤與改造

Observable.create(new Observable.OnSubscribeFunc<T>() {...}); 

這是用來處理:(由於折舊)

Observable.create(new Observable.OnSubscribe<T>() {...}); 

(這可能是因爲最重要的例如,教程,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<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); 
} 

這段代碼幾乎完美,如果一切正常。但是,如果我做出故意的錯誤,就像我關閉WiFi ..比翻新獲得「UnKnownHostException」 ...因爲它應該發生在try catch塊中的翻新調用(getUser)。但不是處理錯誤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以測試錯誤處理。

還有一個用例:如果我添加到observable.onExceptionResumeNext([2nd observable])比第二個observable,並且它不崩潰。但這不是問題的解決方案。

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()); 
     {...} 
    } 

}); 

編輯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) 

預先感謝幫助。

+0

你能發表您的堆棧跟蹤/ logcat的輸出?調用代碼是什麼樣的(觀察者定義)? –

+0

它已被編輯..但實際上它不是太相關,因爲錯誤是故意的。 ... –

+0

上面的輸出是_not你的應用程序crashing_ - 它是[Retrofit記錄錯誤](https://github.com/square/retrofit/blob/2c1c6ec370f88e21ac219d8f343f1f6d904c1c87/retrofit/src/main/java/retrofit/RestAdapter.java #L495)。您是否啓用了logcat過濾器?... –

回答

0

它看起來像您可能正在運行到問題已得到修復爲RxJava 1.0:

TrampolineScheduler NullPointerException

+1

我正在使用rxjava的android模塊,現在jCenter上的最新版本是0.20.7 dependency:compile'c​​om.netflix.rxjava:rxjava-android:0.20.7' –

+1

新版本的[RxAndroid](https:// github.com/ReactiveX/RxAndroid)有一個不同的標識符 - 編譯'io.reactivex:rxandroid:0.24.0'。您還需要將您的RxJava核心模塊升級到1.0。 –

+0

這將是我想的問題。 @AdamS我不確定你的意思「你需要將你的RxJava核心模塊升級到1.0。」順便謝謝你的回答。 –

3

您不必建立自己的可觀測與改造,如改造可以直接返回可觀察:

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

改造還集成RxJava支持與返回類型RX的 方法。Observable

@GET(「/ user/{id}/photo」)Observable getUserPhoto(@Path(「id」) int id);

(你不會自己處理錯誤)

您可以發佈您崩潰的堆棧跟蹤?就像我想的那樣,你的應用程序不應該崩潰。

+1

謝謝,我剛剛學到了一些東西,我修改了代碼,就像你建議,剪掉我所有的Observable,並修改: Observable getUser @Field(「username」)字符串userName,@Field(「password」)字符串密碼); 但問題仍然存在。錯誤未處理,應用程序崩潰。我認爲這不是改裝的問題,而是RX。 並添加了堆棧跟蹤。 –

+0

順便說一句,如果我在處理Observable之前想處理對象,該怎麼辦? - >喜歡這裏,在登錄(用戶名,密碼) - >我想將'憑證'保存到用戶對象中,並且只寫一次而不是應用程序中的所有登錄位。所以在這裏,這個Observable可以在告訴LoginScreen事件發生之前像超級函數一樣操作。 –