7

I am using RxJava and RxBindings for view in android. following is an example of what I am doing.

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

when I click on MyButton, I use flatMap to return another observable which is a network call and can return success or error. when it returns an error i handle it in error block. but I am not able to click the button again.

How can I handle the error and still be able to click on the button again?

g.revolution
  • 11,962
  • 23
  • 81
  • 107

3 Answers3

7

GreyBeardedGeek is spot on. To be quite explicit about one of your options you can use .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");
    });

By the way don't pass null to Observable.error().

Dave Moten
  • 11,957
  • 2
  • 40
  • 47
4

I'm pretty new to RxJava, but just ran across this issue myself.

The problem is that by definition, an Observable will stop emitting values when it's error() method is called.

As far as I can tell, you have two options:

  1. modify the Observable that makes the network call so that when an error occurs, an exception is not thrown, but rather you return a value that indicates that an error occurred. That way, the Observable's error() method will not be called when a network error occurs.

  2. Look into using Observable.onErrorResumeNext to override the termination of the Observable when error() is called. See Best practice for handling onError and continuing processing

Community
  • 1
  • 1
GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67
  • I am using Retrofit so cannot control the network call observable and yes I am currently using `onErrorResumeNext` but the issue with that is that I can only return an observable of the same type and cannot return any other type of object. and thats what I don't like about `onErrorResumeNext` – g.revolution Aug 19 '15 at 04:32
  • Just because you're using Retrofit doesn't mean that you have to use it's Observable methods. You can wrap a Retrofit synchronous call in your own Observable. – GreyBeardedGeek Aug 25 '15 at 19:52
2

I use approach similar to already described:

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

I have a short article which describes this approach.

marwinXXII
  • 1,456
  • 14
  • 21