Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle Network error with Retrofit observable

When using Observables with Retrofit how do you handle Network failure?

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

The request just fails without network and onError is not called. It does not crash, but fails silently. Logs shows Retrofit getting the error:

 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)

Using callbacks this is simply passed to the onFailure(RetrofitError error). How can I get this surfaced with RxJava?

like image 788
Patrick Avatar asked Aug 08 '14 22:08

Patrick


2 Answers

My problem was actually elsewhere in my code. Handling network errors with rxJava + Retrofit is very easy as it just throws a RetrofitError in the onError method:

 @Override
 public void onError(Throwable e) {
     if (e instanceof RetrofitError) {
        if (((RetrofitError) e).isNetworkError()) {
            //handle network error
        } else {
            //handle error message from server
        }
     }
 }
like image 125
Patrick Avatar answered Nov 14 '22 02:11

Patrick


This is purely an RxJava issue, not involving that much from Retrofit. doOnError is a side-effect, so even though it handles the error, it does not "catch" in the sense of preventing it from bubbling forwards.

You should look at Error Handling Operators. The most basic option is onErrorReturn() which allows you to substitute an error with an item (instance of GetJobResponse).

You can put an "error" flag on that item in order to identify it later when you subscribe to the observable. Also it's important to know that if you don't subscribe to that observable, it is essentially "dead". You should always subscribe to observables rather than using "doOn___" which are just side-effects (should be used for logging and other non-critical functionality).

like image 25
André Staltz Avatar answered Nov 14 '22 00:11

André Staltz