Как можно обработать ошибки в RxJava?android-51

В RxJava существует несколько механизмов обработки ошибок, которые позволяют контролировать поток данных при возникновении исключений. Рассмотрим основные подходы.

1. onError в subscribe

Самый простой способ - обработка ошибки в подписчике:

Observable.error(new RuntimeException("Oops!"))
    .subscribe(
        item -> System.out.println("Received: " + item),
        error -> System.out.println("Error: " + error.getMessage()) // Обработка ошибки
    );
  • Плюсы: Простота использования
  • Минусы: Прерывает весь поток, после ошибки не будут приходить новые элементы

2. Операторы обработки ошибок

a) onErrorReturn

Заменяет ошибку конкретным значением:

Observable.error(new RuntimeException("Error"))
    .onErrorReturn(e -> "Default Value")
    .subscribe(item -> System.out.println(item)); // Выведет "Default Value"

b) onErrorResumeNext

Позволяет продолжить работу с другим Observable при ошибке:

Observable.error(new RuntimeException("Error"))
    .onErrorResumeNext(Observable.just("Fallback", "Values"))
    .subscribe(item -> System.out.println(item)); // Выведет "Fallback", затем "Values"

c) retry

Повторяет подписку при возникновении ошибки:

Observable.create(emitter -> {
    // Имитация ненадежного источника
    if (Math.random() > 0.5) {
        emitter.onNext("Success");
        emitter.onComplete();
    } else {
        emitter.onError(new RuntimeException("Failed"));
    }
})
.retry(3) // Попробует максимум 3 раза
.subscribe(...);
  • retryWhen(): Более сложная версия с возможностью задержки между попытками

3. Глобальный обработчик ошибок

Для неперехваченных ошибок можно установить глобальный обработчик:

RxJavaPlugins.setErrorHandler(e -> {
    if (e instanceof UndeliverableException) {
        // Обработка недоставленных ошибок
    }
    // Логирование и т.д.
});

4. Особенности для Android

При работе с Android важно:

  • Всегда обрабатывать ошибки в цепочках, работающих с UI
  • Использовать observeOn(AndroidSchedulers.mainThread()) для обработки ошибок в UI потоке
  • Не забывать отписываться при ошибках (особенно в Activity/Fragment)

Пример безопасной работы:

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();
}

Резюмируем:

  1. Используйте onError в subscribe() для базовой обработки
  2. Применяйте операторы (onErrorReturn, onErrorResumeNext, retry) для более сложных сценариев
  3. Настраивайте глобальный обработчик для неперехваченных исключений
  4. На Android особое внимание уделяйте потокам и жизненному циклу компонентов
  5. Всегда обрабатывайте ошибки - не оставляйте цепочки без обработчиков