RxJava/RxBinding: как обрабатывать ошибки в RxView

Я использую RxJava и RxBindings для просмотра в Android. Ниже приведен пример того, что я делаю.

    RxView.clicks(btMyButton).flatMap(btn -> {
        // another observable which can throw onError.
        return Observable.error(null);
    }).subscribe(object -> {
        Log.d("CLICK", "button clicked");
    }, error -> {
        Log.d("CLICK", "ERROR");
    });

когда я нажимаю MyButton, я использую flatMap для возврата другого наблюдаемого объекта, который является сетевым вызовом и может возвращать успех или ошибку. когда он возвращает ошибку, я обрабатываю ее в блоке ошибок. но я не могу нажать кнопку еще раз.

Как я могу обработать ошибку и по-прежнему иметь возможность снова нажать на кнопку?


person g.revolution    schedule 19.08.2015    source источник


Ответы (3)


GreyBeardedGeek на высоте. Чтобы четко указать один из ваших вариантов, вы можете использовать .materialize():

RxView.clicks(btMyButton).flatMap(btn -> {
        if (ok) 
            return someObservable.materialize();
        else 
            return Observable.error(new MyException()).materialize();
    }).subscribe(notification -> {
        if (notification.hasValue())
            Log.d("CLICK", "button clicked");
        else if (notification.isOnError())
             Log.d("CLICK", "ERROR");
    });

Кстати, не передавайте null в Observable.error().

person Dave Moten    schedule 19.08.2015
comment
конечно, попробую этот вариант и посмотрим. и да null был только для этого примера :) - person g.revolution; 19.08.2015

Я новичок в RxJava, но сам столкнулся с этой проблемой.

Проблема в том, что по определению Observable перестанет выдавать значения при вызове метода error().

Насколько я понимаю, у вас есть два варианта:

  1. измените Observable, который выполняет сетевой вызов, чтобы при возникновении ошибки не выбрасывалось исключение, а возвращалось значение, указывающее, что произошла ошибка. Таким образом, метод error() объекта Observable не будет вызываться при возникновении сетевой ошибки.

  2. Изучите использование Observable.onErrorResumeNext, чтобы переопределить завершение Observable при вызове error(). См. Рекомендации по обработке onError и продолжению обработки

person GreyBeardedGeek    schedule 19.08.2015
comment
Я использую Retrofit, поэтому не могу управлять наблюдаемым сетевым вызовом, и да, в настоящее время я использую onErrorResumeNext, но проблема в том, что я могу возвращать только наблюдаемый объект того же типа и не могу возвращать объект любого другого типа. вот что мне не нравится в onErrorResumeNext - person g.revolution; 19.08.2015
comment
Тот факт, что вы используете Retrofit, не означает, что вы должны использовать его методы Observable. Вы можете обернуть синхронный вызов Retrofit в свой собственный Observable. - person GreyBeardedGeek; 25.08.2015

Я использую подход, аналогичный уже описанному:

RxView.clicks(btMyButton)
  .flatMap(btn -> {
    // another observable which can throw onError.
    return Observable.error(null)
      .doOnError(error -> {
      //handle error
      })
      .onErrorResumeNext(Observable.empty());//prevent observable from terminating
  })
  .subscribe(object -> {
      Log.d("CLICK", "button clicked");//here no errors should occur
  });

У меня есть короткая статья, в которой описывается этот подход.

person marwinXXII    schedule 21.08.2015