ここに私が思いついた解決策があります。 私はそれを改善するつもりならば、私はここに変更を掲載します。
私の問題を解決するには、(例外は改修によって飲み込まれRxJavaによって処理されていない)だけで、エラーを発するので、私は例外を「再スロー」ができることを新たに観察できるが作成されますObservable.error方法です。
私はretrofit.Resultを出すすべての残りの呼び出しに追加する観測可能なトランスフォーマを作成しました。 このトランスフォーマはObservable>をとり、エラーがなければObservable>に変換します。エラーがある場合、カスタムHttp * Exceptionsを持つObservable.errorを返します。これは、後でオブザーバーでonErrorコールバックで処理できます。 ObservableTransformations.resultToResponseWithHttpErrorHandlingというユーティリティクラスの静的メソッドとして記述します。ここ
それは:
public class ObservableTransformations {
public static <T> Observable.Transformer<Result<T>, Response<T>> resultToResponseWithHttpErrorHandling() {
return observable -> observable.flatMap(r -> {
Observable<Response<T>> returnObservable = Observable.just(r.response());
if (r.isError()) {
Throwable throwable = r.error();
if (throwable instanceof IOException) {
Timber.e(throwable, "Retrofit connection error.");
// TODO Check this cases
if (throwable instanceof java.net.ConnectException) {
returnObservable = Observable.error(new HttpNoInternetConnectionException());
} else if (throwable instanceof SocketTimeoutException) {
returnObservable = Observable.error(new HttpServerDownException());
} else {
returnObservable = Observable.error(new HttpNoInternetConnectionException());
}
} else {
Timber.e(throwable, "Retrofit general error - fatal.");
returnObservable = Observable.error(new HttpGeneralErrorException(r.error()));
}
} else {
Response<T> retrofitResponse = r.response();
if (!retrofitResponse.isSuccess()) {
int code = retrofitResponse.code();
String message = "";
try {
message = retrofitResponse.errorBody().string();
} catch (IOException e) {
Timber.e(e, "Error reading errorBody from response");
}
Timber.i("Server responded with error. Code: " + code + " message: " + message);
Throwable t = null;
if (NetworkUtils.isClientError(code)) {
t = new HttpClientException(retrofitResponse.code(), message);
} else if (NetworkUtils.isServerError(code)) {
t = new HttpServerErrorException(retrofitResponse.code(), message);
}
returnObservable = Observable.error(t);
}
}
return returnObservable;
}).retryWhen(new RetryWithDelayIf(3, 1000, t -> {
return (t instanceof HttpNoInternetConnectionException) || (t instanceof HttpServerDownException);
}));
}
}
リトライは、指数バックオフを使用して3回行われ、例外がHttpNoInternetConnectionException又はHttpServerDownException場合のみ。
RetryWithDelayIfクラスはこちらです。再試行の条件は、コンストラクタの最後の引数(throwableを取る関数で、このthrowableが再試行をトリガする必要がある場合はtrue、そうでない場合はfalseを返す関数)が必要です。あなたの観察者ののonErrorで
restService.login(new LoginRestRequest(username, password))
.compose(ObservableTransformations.resultToResponseWithHttpErrorHandling());
はあなたが最終的にHTTPは*例外を処理することができます:
public class RetryWithDelayIf implements
Func1<Observable<? extends Throwable>, Observable<?>> {
private final int maxRetries;
private final int retryDelayMillis;
private int retryCount;
private Func1<Throwable, Boolean> retryIf;
public RetryWithDelayIf(final int maxRetries, final int retryDelayMillis, Func1<Throwable, Boolean> retryIf) {
this.maxRetries = maxRetries;
this.retryDelayMillis = retryDelayMillis;
this.retryCount = 0;
this.retryIf = retryIf;
}
@Override
public Observable<?> call(Observable<? extends Throwable> attempts) {
return attempts.zipWith(Observable.range(1, maxRetries + 1), (n, i) -> {
return new Tuple<Throwable, Integer>(n, i);
})
.flatMap(
ni -> {
if (retryIf.call(ni.getFirst()) && ni.getSecond() <= maxRetries) {
return Observable.timer((long) Math.pow(2, ni.getSecond()), TimeUnit.SECONDS);
} else {
return Observable.error(ni.getFirst());
}
});
}
}
最後に、ここでrestServiceコールでの使用です。
リンクを参照してください。http://bytes.babbel.com/en/articles/2016-03-16-retrofit2-rxjava-error-handling.html _Retrofit.Builder_の_RxJavaCallAdapterFactory_をオーバーライドする方法について説明しています。 _ Observable.onResumeErrorNext_/_Observable.onDoNext()_ – murt