web-dev-qa-db-ja.com

Retrofitオブザーバブルでネットワークエラーを処理する

ObservablesをRetrofitで使用する場合、ネットワーク障害をどのように処理しますか?

このコードを考えると:

Observable<GetJobResponse> observable = api.getApiService().getMyData();
observable
    .doOnNext(new Action1<GetJobResponse>() {
        @Override
        public void call(GetJobResponse getJobResponse) {
            //do stuff with my data
        }
    })
    .doOnError(new Action1<Throwable>() {
        @Override
        public void call(Throwable throwable) {
            //do stuff with error message
        }
    });

リクエストはネットワークなしで失敗し、onErrorは呼び出されません。クラッシュはしませんが、静かに失敗します。ログはレトロフィットがエラーを取得していることを示しています:

 Java.net.UnknownHostException: Unable to resolve Host "api-staging.sittercity.com": No address associated with hostname
     at Java.net.InetAddress.lookupHostByName(InetAddress.Java:424)
     at Java.net.InetAddress.getAllByNameImpl(InetAddress.Java:236)
     at Java.net.InetAddress.getAllByName(InetAddress.Java:214)
     at com.squareup.okhttp.internal.Dns$1.getAllByName(Dns.Java:29)

コールバックを使用して、これは単にonFailure(RetrofitErrorエラー)に渡されます。 RxJavaでこれを表示するにはどうすればよいですか?

20
Patrick

私の問題は実際には私のコードのどこかにありました。 rxJava + Retrofitでのネットワークエラーの処理は、onErrorメソッドでRetrofitErrorをスローするだけなので非常に簡単です。

 @Override
 public void onError(Throwable e) {
     if (e instanceof RetrofitError) {
        if (((RetrofitError) e).isNetworkError()) {
            //handle network error
        } else {
            //handle error message from server
        }
     }
 }
33
Patrick

これは純粋にRxJavaの問題であり、Retrofitの問題はそれほど多くありません。 doOnErrorは副作用であるため、エラーを処理しても、前方にバブリングするのを防ぐという意味では「キャッチ」しません。

エラー処理演算子 を見てください。最も基本的なオプションはonErrorReturn()で、これを使用してエラーをアイテム(GetJobResponseのインスタンス)に置き換えることができます。

後でobservableをサブスクライブするときにそれを識別するために、そのアイテムに「エラー」フラグを付けることができます。また、そのオブザーバブルをサブスクライブしないと、本質的に「デッド」になることを知っておくことが重要です。単なる副作用である「doOn___」を使用するのではなく、常にオブザーバブルをサブスクライブする必要があります(ロギングおよびその他の重要でない機能に使用する必要があります)。

12
André Staltz

オブザーバブルをonErrorで放出させると、onErrorReturnonErrorResumeNextのどちらで「キャッチ」するかに関係なく、上流のすべてのオブザーバブルがシャットダウンします。多くの場合、それは必要ありません。たとえば、ストリームが改造リクエストをトリガーするボタンクリックで始まった場合、ストリームが終了したため、ボタンクリックは認識されなくなります。

_Observable<Response<Type>>_または_Observable<Result<Type>>_を使用して、onNext()の改造エラーも処理します。

s。 http://blog.danlew.net/2015/12/08/error-handling-in-rxjava/

0
Till

Retrofit2およびRxJava2以降、RetrofitError例外はなくなりました。そして、その後継HttpExceptionは、HTTPエラー応答コードのみを表します。ネットワークエラーはIOExceptionを通じて処理する必要があります。

 @Override
 public void onError(Throwable e) {
     if (e instanceof IOException) {
            //handle network error
     } else if (e instanceof HttpException) {
            //handle HTTP error response code
     } else {
            //handle other exceptions
     } 
 }