यहां समाधान है जिसके साथ मैं आया था। यदि मैं इसे बेहतर बनाउंगा तो मैं यहां परिवर्तन पोस्ट करूंगा।
मेरी समस्या (अपवाद रेट्रोफिट द्वारा निगल लिया और RxJava द्वारा नियंत्रित नहीं) का हल Observable.error विधि है कि एक नए नमूदार बनाता है कि केवल त्रुटि का उत्सर्जन करता है है, इसलिए मैं अपवाद "rethrow" कर सकते हैं।
मैं हर बाकी कॉल है कि एक retrofit.Result का उत्सर्जन करता है करने के लिए संलग्न करने के लिए एक नमूदार ट्रांसफार्मर बनाया। यह ट्रांसफॉर्मर एक अवलोकन लेता है> और, यदि प्रतिक्रिया में कोई त्रुटि नहीं है, तो इसे एक अवलोकन में बदल देती है>। यदि त्रुटियां हैं तो यह एक पर्यवेक्षक लौटाता है। कस्टम एचटीपी * अपवाद के साथ आतंक जिसे मैं बाद में अपने ऑब्जर्वर में ऑनर कॉलबैक में संभाल सकता हूं। मैं 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);
}));
}
}
पुन: प्रयास करें एक घातीय backoff का उपयोग कर 3 बार किया जाता है, और केवल यदि अपवाद HttpNoInternetConnectionException या HttpServerDownException है।
RetryWithDelayIf कक्षा यहां है। कन्स्ट्रक्टर के आखिरी तर्क के रूप में पुनः प्रयास करने के लिए स्थिति को पूरा किया जाता है (एक फंक्शन फेंकने योग्य और सही लौटने पर यदि यह फेंकने योग्य पुनः प्रयास करना चाहिए और गलत नहीं है)।
restService.login(new LoginRestRequest(username, password))
.compose(ObservableTransformations.resultToResponseWithHttpErrorHandling());
onError अपने पर्यवेक्षक की में आप अंत में 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