Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle all types of Retrofit errors properly with rxjava

I'm new to Rxjava with Retrofit and I'm asking for the best right way to handle all possible status in Retrofit using rxjava and rxbinding which includes:

  1. No Internet connection.
  2. Null response from server.
  3. Success response.
  4. Error response and show the error message like Username or password is incorrect.
  5. Other errors like connection reset by peers.
like image 452
alihabbash95 Avatar asked Oct 17 '22 14:10

alihabbash95


1 Answers

I'm having exception subclass for each important failure response. Exceptions are delivered as Observable.error(), while values are delivered through stream without any wrapping.

1) No internet - ConnectionException

2) Null - just NullPointerException

4) Check for "Bad Request" and throw IncorrectLoginPasswordException

5) any other error is just NetworkException

You can map errors with onErrorResumeNext() and map()

For example

Typical retrofit method that fetches data from web service:

public Observable<List<Bill>> getBills() {
    return mainWebService.getBills()
            .doOnNext(this::assertIsResponseSuccessful)
            .onErrorResumeNext(transformIOExceptionIntoConnectionException());
}

Method that assures response is ok, throws appropriate exceptions otherwise

private void assertIsResponseSuccessful(Response response) {
    if (!response.isSuccessful() || response.body() == null) {
        int code = response.code();
        switch (code) {
            case 403:
                throw new ForbiddenException();
            case 500:
            case 502:
                throw new InternalServerError();
            default:
                throw new NetworkException(response.message(), response.code());
        }

    }
}

IOException means there is no network connection so I throw ConnectionException

private <T> Function<Throwable, Observable<T>> transformIOExceptionIntoConnectionException() {
    // if error is IOException then transform it into ConnectionException
    return t -> t instanceof IOException ? Observable.error(new ConnectionException(t.getMessage())) : Observable.error(
            t);
}

For your login request create new method that will check if login/password are ok.

And at the end there is

subscribe(okResponse -> {}, error -> {
// handle error
});
like image 88
Tuby Avatar answered Oct 21 '22 01:10

Tuby