web-dev-qa-db-fra.com

Gérer l'erreur de réseau avec Retrofit observable

Lorsque vous utilisez Observables avec Retrofit, comment gérez-vous les pannes de réseau?

Compte tenu de ce code:

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
        }
    });

La requête échoue simplement sans réseau et onError n'est pas appelée. Il ne plante pas, mais échoue silencieusement. Les journaux indiquent que Retrofit obtient l'erreur:

 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)

À l'aide de rappels, cela est simplement transmis à onFailure (erreur RetrofitError). Comment puis-je obtenir cette surface avec RxJava?

20
Patrick

Mon problème était en fait ailleurs dans mon code. La gestion des erreurs réseau avec rxJava + Retrofit est très facile car elle lance simplement un RetrofitError dans la méthode onError:

 @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

Ceci est purement un problème RxJava, n'impliquant pas beaucoup de Retrofit. doOnError est un effet secondaire, donc même s'il gère l'erreur, il ne se "rattrape" pas dans le sens de l'empêcher de se propager vers l'avant.

Vous devriez regarder Opérateurs de gestion des erreurs . L'option la plus basique est onErrorReturn() qui vous permet de remplacer une erreur par un élément (instance de GetJobResponse).

Vous pouvez placer un indicateur "erreur" sur cet élément afin de l'identifier plus tard lorsque vous vous abonnez à observable. Il est également important de savoir que si vous ne souscrivez pas à cet observable, il est essentiellement "mort". Vous devez toujours vous abonner aux observables plutôt que d'utiliser "doOn___" qui ne sont que des effets secondaires (doivent être utilisés pour la journalisation et d'autres fonctionnalités non critiques).

12
André Staltz

Notez que si vous laissez un observable émettre onError, tous les observables en amont s'arrêteront, que vous le "capturiez" avec onErrorReturn ou onErrorResumeNext. Souvent, vous ne voulez pas ça. Par exemple, si votre flux commence par un clic sur un bouton qui déclenche une demande de modification qui échoue, les clics sur le bouton ne seront plus reconnus depuis la fin du flux.

Utilisez Observable<Response<Type>> Ou Observable<Result<Type>> Pour gérer également les erreurs de modification dans onNext().

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

0
Till

En date du Retrofit2 et RxJava2 il n'y a plus d'exception RetrofitError. Et son successeur HttpException ne représente que les codes de réponse aux erreurs HTTP. Les erreurs réseau doivent être gérées via 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
     } 
 }
0