В RxJava существует несколько механизмов обработки ошибок, которые позволяют контролировать поток данных при возникновении исключений. Рассмотрим основные подходы.
Самый простой способ - обработка ошибки в подписчике:
Observable.error(new RuntimeException("Oops!"))
.subscribe(
item -> System.out.println("Received: " + item),
error -> System.out.println("Error: " + error.getMessage()) // Обработка ошибки
);
Заменяет ошибку конкретным значением:
Observable.error(new RuntimeException("Error"))
.onErrorReturn(e -> "Default Value")
.subscribe(item -> System.out.println(item)); // Выведет "Default Value"
Позволяет продолжить работу с другим Observable при ошибке:
Observable.error(new RuntimeException("Error"))
.onErrorResumeNext(Observable.just("Fallback", "Values"))
.subscribe(item -> System.out.println(item)); // Выведет "Fallback", затем "Values"
Повторяет подписку при возникновении ошибки:
Observable.create(emitter -> {
// Имитация ненадежного источника
if (Math.random() > 0.5) {
emitter.onNext("Success");
emitter.onComplete();
} else {
emitter.onError(new RuntimeException("Failed"));
}
})
.retry(3) // Попробует максимум 3 раза
.subscribe(...);
Для неперехваченных ошибок можно установить глобальный обработчик:
RxJavaPlugins.setErrorHandler(e -> {
if (e instanceof UndeliverableException) {
// Обработка недоставленных ошибок
}
// Логирование и т.д.
});
При работе с Android важно:
observeOn(AndroidSchedulers.mainThread())
для обработки ошибок в UI потокеПример безопасной работы:
disposable = networkService.getData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
data -> updateUi(data),
error -> showError(error) // Обработка в UI потоке
);
// В onDestroy():
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
onError
в subscribe()
для базовой обработкиonErrorReturn
, onErrorResumeNext
, retry
) для более сложных сценариев