модернизация с использованием rxjava сетевых исключений в глобальном масштабе

Я пытаюсь обрабатывать исключения в приложении на глобальном уровне, так что retrofit выдает ошибку, которую я улавлю в определенном classе с логикой для обработки этих ошибок.

У меня есть интерфейс

@POST("/token") AuthToken refreshToken(@Field("grant_type") String grantType, @Field("refresh_token") String refreshToken); 

и наблюдаемые

 /** * Refreshes auth token * * @param refreshToken * @return */ public Observable refreshToken(String refreshToken) { return Observable.create((Subscriber subscriber) -> { try { subscriber.onNext(apiManager.refreshToken(REFRESH_TOKEN, refreshToken)); subscriber.onCompleted(); } catch (Exception e) { subscriber.onError(e); } }).subscribeOn(Schedulers.io()); } 

Когда я получаю 401 с сервера (неверный токен или какая-либо другая связанная с сетью ошибка), я хочу обновить токен и повторить остальные вызовы. Есть ли способ сделать это с помощью rxjava для всех вызовов останова с каким-то наблюдаемым, который поймает эту ошибку во всем мире, обработает ее и повторит вызов, который его выбрал?

На данный момент я использую тему, чтобы поймать ошибку на .subscribe (), как это

 private static BehaviorSubject errorEvent = BehaviorSubject.create(); public static BehaviorSubject getErrorEvent() { return errorEvent; } 

и в некоторых случаях

 getCurrentUser = userApi.getCurrentUser().observeOn(AndroidSchedulers.mainThread()) .subscribe( (user) -> { this.user = user; }, errorEvent::onNext ); 

то в моем основном действии я подписываюсь на этот предмет поведения и разбираю ошибку

 SomeApi.getErrorEvent().subscribe( (e) -> { //parse the error } ); 

но я не могу повторить вызов наблюдаемого, который выдает ошибку.

Вам нужно использовать оператор onErrorResumeNext(Func1 resumeFunction) , лучше объясненный в официальной вики :

Метод onErrorResumeNext () возвращает Observable, который отражает поведение источника Observable, если только Observable не вызывает onError (), и в этом случае вместо того, чтобы распространять эту ошибку для Абонента, onErrorResumeNext () вместо этого начнет зеркалировать вторую резервную копию Observable

В вашем случае я бы сказал что-то вроде этого:

 getCurrentUser = userApi.getCurrentUser() .onErrorResumeNext(refreshTokenAndRetry(userApi.getCurrentUser())) .observeOn(AndroidSchedulers.mainThread()) .subscribe(...) 

где:

  private  Func1> refreshTokenAndRetry(final Observable toBeResumed) { return new Func1>() { @Override public Observable call(Throwable throwable) { // Here check if the error thrown really is a 401 if (isHttp401Error(throwable)) { return refreshToken().flatMap(new Func1>() { @Override public Observable call(AuthToken token) { return toBeResumed; } }); } // re-throw this error because it's not recoverable from here return Observable.error(throwable); } }; } 

Обратите также внимание на то, что эта функция может быть легко использована в других случаях, поскольку она не набирается с фактическими значениями, полученными возобновленным Observable.

 @Override public Observable> messages(String accountId, int messageType) { return mMessageService.getLikeMessages(messageType) .onErrorResumeNext(mTokenTrick. refreshTokenAndRetry(mMessageService.getLikeMessages(messageType))); } 
Interesting Posts
Давайте будем гением компьютера.