Home > other >  RxJava fromCallable() and defer() difference in behaviour
RxJava fromCallable() and defer() difference in behaviour

Time:01-12

I have implement a validate function, sample code are as below:

public class TestObject {
  LocalDateTime d1;
  LocalDateTime d2;

  //getters, setters
}

public class ErrorResult {
  String errorMsg;
  
  public ErrorResult(String errorMsg){
    this.errorMsg = errorMsg;
  }
}

public Observable<ErrorResult> validate(TestObject testObject){
  // implementation section
}

For the implementation section, I have tried to use Observable.fromCallable() and Observable.defer() functions to do the same job, for example:

// for implementation using Observable.fromCallable
return Observable.fromCallable(() -> {
  LocalDateTime d1 = testObject.getD1();
  LocalDateTime d2 = testObject.getD2();
  if(d1.isBefore(d2))
    return Observable.just(new ErrorResult("Error d1 is before d2"));

  return Observable.empty();
});

// for implementation using Observable.defer
return Observable.defer(() -> {
  LocalDateTime d1 = testObject.getD1();
  LocalDateTime d2 = testObject.getD2();
  if(d1.isBefore(d2))
    return Observable.just(new ErrorResult("Error d1 is before d2"));

  return Observable.empty();
});

While the implementation of the logic within the anonymous functions is the same,

  • the implementation using Observable.fromCallable throw a compilation error in IDE (Intellij), which stated "no instance(s) of type variable(s) T exist so that Observable conforms to ErrorResult". It was caused by the return of Observable.empty() as the fallback return in case no error exists
  • the implementation using Observable.defer compile successfully without error

May I know what is the difference between Observable.fromCallable() and Observable.defer() in this case?

Thanks a lot for the help

CodePudding user response:

fromCallable is not designed to return an Observable, while defer is. So in your example with fromCallable, you're ending up with a Observable<Observable<ErrorResult>>. You actually can't get your desired behavior with fromCallable, because you can't use it to get an empty Observable (returning null from the Callable results in a NullPointerException).

  • Related