2016-09-12 16 views
2

Я использую RxJava и Retrofit2 (с OkHttp как HTTP-клиент) для создания сетей и пытаюсь понять, как обрабатываются различные ошибки Retrofit2 и как они выглядят со стороны RxJava. Следующий код иллюстрирует обратный вызов Абонента RxJava для сетевого вызова (сделанный с помощью Retrofit).Обработка ошибок Retrofit2 + RxJava

 Subscription subscription = observable 
      .subscribeOn(mScheduler) 
      .observeOn(mAndroidScheduler) 
      .subscribe(new Subscriber<User>() { 
       @Override 
       public void onCompleted() { 
        Timber.d("onCompleted called"); 
        mRetainerView.clearUserObservable(); 
        mActivityView.hideProgressBar(); 
        mActivityView.enableUi(); 
       } 

       @Override 
       public void onError(Throwable e) { 
        Timber.d("onError called"); 
        Timber.d(e.toString()); 
        mRetainerView.clearUserObservable(); 
        mActivityView.hideProgressBar(); 
        mActivityView.enableUi(); 
       } 

       @Override 
       public void onNext(User user) { 
        Timber.d("onNext called"); 
        mRetainerView.clearUserObservable(); 
        mActivityView.hideProgressBar(); 
        mActivityView.enableUi(); 
        mActivityView.launchMainActivity(); 
       } 
      }); 

Мой вопрос, в каких случаях будет OnError() можно назвать и как только он был назван, как я могу допросить Throwable, чтобы определить причину?

Из источника «Дооснащение» это выглядит как только Throwables, которые можно увидеть, это IOException и HttpException. Может ли кто-нибудь проверить, что это правда?

ответ

5

Вот основы: onError() будет вызываться, если:

  • observable вы подписавшись на сгенерирует исключение (например, вы получаете IOException при попытке чтения файла)
  • возбуждается исключение в вашем методе onNext().

Если есть исключение в вашем onComplete(), RxJava будет распространяться в rx.exceptions.OnCompletedFailedException и если есть исключение в onError() - вы получите rx.exceptions.OnErrorFailedException.

Это, пожалуйста, вы можете просто ввести Throwable, который вы получаете в своем методе onError() для исключений, которые вы ожидаете. Например, вы знаете, что если ваш вызов API приведет к ошибке клиента (4xx), Retrofit перевернет его в HttpException. Если у вас есть тайм-аут с запросом, вы получите SocketTimeoutException. Вот грубый пример:

@Override 
public void onError(Throwable e) { 
    Timber.d("onError called"); 
    Timber.d(e.toString()); 
    handleError(e); 
} 

private handleError(Throwable throwable) { 
    if (throwable instanceof HttpException) { 
     HttpException httpException = (HttpException)throwable; 
     int statusCode = httpException.code(); 
     // handle different HTTP error codes here (4xx) 
    } else if (throwable instanceof SocketTimeoutException) { 
     // handle timeout from Retrofit 
    } else if (throwable instanceof IOException) { 
     // file was not found, do something 
    } else { 
     // generic error handling 
     mRetainerView.clearUserObservable(); 
     mActivityView.hideProgressBar(); 
     mActivityView.enableUi(); 
} 
0

Не используйте onError для потока. Это будет так же плохо, как try-catch для потока.

Ошибка HTTP-кодов, действительные ответы, и вы не должны иметь дело с ними в onError. Вы можете обернуть возвращаемый тип своих услуг по обновлению в Result, что дает вам возможность получать информацию о том, что происходит с вашим вызовом, не исключая исключения.

Вы можете обрабатывать состояние вашего приложения, используя этот шаблон:

service.getSomething() 
     .map(r -> Model.success(r.response())) 
     .onErrorReturn(Model::error) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .startWith(Resource.loading()) 
     .subscribe(r -> { 
      myProgressBar.setVisible(r.isLoading()); 
      if (r.isSuccess()) { 
       handleSuccess(); // e.g. 400 is also success but needs handling 
      } 
      if (r.isError()) { 
       handleError(); 
      } 
     }, OnErrorNotImplementedException::new); 

Посмотрите, как я пытался обрабатывать все возможные состояния в потоке и намеренно я бросаю OnErrorNotImplementedException за то, что я, возможно, уже пропустил. Это очень личное, но я предпочитаю крах-быстро-и-ярость, а не находиться в неизвестном состоянии на некоторое время, которое позже проявится в сложном случае, чтобы отладить.

Смежные вопросы