fromCallable
and defer
have different implementation. I heard some say that defer
helps with recursion but i can't produce any code that shows the difference between them.
i tried with infinite number implementation:
private Observable<Integer> numbers(int start) {
return Observable.just(start)
.concatWith(Observable.defer(() -> numbers(start + 1)));
}
but i still get stack overflow exception when subscribing
fromCallable
creates observable that emits single value, then completes.
defer
postpones creation of actual observable until it is subscribed to. So you can create multi-value observable based on state at time of subscription. For example:
Observable<Integer> daysOfWeekLeft =
Observable.defer(() ->
Observable.range(currentDayOfWeek(), 7 - currentDayOfWeek()));
Basically you can achieve the same with fromCallable
like this:
Observable<Integer> daysOfWeekLeft =
Observable.fromCallable(() -> currentDayOfWeek())
.flatMap(day -> Observable.range(day, 7 - day));
PS. Your code for infinite stream of numbers results in infinite recursion. Might need to play with schedulers to avoid that.
I was looking at it terms of Single
, which is less complicated than Observable, because it can only have 1 value. (i.e. An observable with 1 emission). The following applies to the other types as well (Observable, Flowable, Completable)
Single.fromCallable
Single.fromCallable
actually creates a new Single from the value inside the function it calls. This is why Aaron He said is comment:
fromCallable is kinda a convenient method for Observable.defer(() -> Observable.just(value))
It does that extra step of creating an Observable by using .just
. If you call a function fromCallable
which already creates a Single, you'll get a nested single.
// Not very useful to get a Single<Single<*>>
val fromCallable: Single<Single<String>> = Single.fromCallable {
Single.just("Example")
}
// Better in these cases, where the function inside doesn't create a Single already:
fun heavyFunction(): String { return "Heavy" }
val fromCallable2: Single<String> = Single.fromCallable {heavyFunction()}
Single.defer
Single.defer
calls the function inside it, if it returns a Single, then you can use that Single later on. If it doesn't, it won't compile.
val defer: Single<String> = Single.defer {
Single.just("Example")
}
// This line won't compile:
Single.defer {heavyFunction()}
// You need to wrap it in a Single:
val defer2: Single<String> = Single.defer {Single.just(heavyFunction())}
So, Single.fromCallable creates a Single from a callable, hence the name. This callable that doesn't have to create a Single, it can be anything.
Defer doesn't create a new Single, it just calls its body which should create a Single. That's why it doesn't have the from
in its function name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With