RxJava Single.just() vs Single.fromCallable()?
Asked Answered
T

4

41

I wondered if someone can shed some light on this question, when to use

Single.fromCallable( ()-> myObject )

instead of

Single.just(myObject)

from the documentation, Single.fromCallable():

 /**
 * Returns a {@link Single} that invokes passed function and emits its result for each new SingleObserver that subscribes.
 * <p>
 * Allows you to defer execution of passed function until SingleObserver subscribes to the {@link Single}.
 * It makes passed function "lazy".
 * Result of the function invocation will be emitted by the {@link Single}.
 * <dl>
 *   <dt><b>Scheduler:</b></dt>
 *   <dd>{@code fromCallable} does not operate by default on a particular {@link Scheduler}.</dd>
 * </dl>
 *
 * @param callable
 *         function which execution should be deferred, it will be invoked when SingleObserver will subscribe to the {@link Single}.
 * @param <T>
 *         the type of the item emitted by the {@link Single}.
 * @return a {@link Single} whose {@link SingleObserver}s' subscriptions trigger an invocation of the given function.
 */

and the documentation for Single.just():

 /**
 * Returns a {@code Single} that emits a specified item.
 * <p>
 * <img width="640" height="310" src="https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/Single.just.png" alt="">
 * <p>
 * To convert any object into a {@code Single} that emits that object, pass that object into the
 * {@code just} method.
 * <dl>
 * <dt><b>Scheduler:</b></dt>
 * <dd>{@code just} does not operate by default on a particular {@link Scheduler}.</dd>
 * </dl>
 *
 * @param item
 *            the item to emit
 * @param <T>
 *            the type of that item
 * @return a {@code Single} that emits {@code item}
 * @see <a href="http://reactivex.io/documentation/operators/just.html">ReactiveX operators documentation: Just</a>
 */
Tricho answered 5/10, 2018 at 17:25 Comment(0)
U
58

In the use case you've mentioned, there is actually no major difference.

Now imagine we need the object to be created dynamically through a function call?

fun getTimeObject() {
    val timeInMillis = System.currentTimeMillis()
    return TimeObject(timeInMillis)
}

Then with, Single.just(getTimeObject()) the resulting Single will emit the same Long when it has a new subscriber.

However, with Single.fromcallable(()-> getTimeObject()), the resulting Single will emit a different Long indicating the current time in millis when it has a new subscriber.

That's because fromCallable executes it's lambda everytime it has a new subscriber Lazily.

Unnerve answered 5/10, 2018 at 18:50 Comment(1)
I found this example excellent, because it shows significant difference between these 2 functions in very short lines. Should be written into a textbook!Hexastyle
A
67

Usually you will notice the difference when the thing you're emitting is not just an object but actually a result of some method calls that involve either heavy computation, I/O, or state.

Single.just(x) evaluates the x immediately in the current thread and then you're left with whatever was the result of x, for all subscribers.

Single.fromCallable(y) invokes the y callable in the subscribeOn scheduler at the time of subscription and separately for each subscriber.


So for example, if you wanted to offload an I/O operation to a background thread, you'd use

Single.fromCallable(() -> someIoOperation()).
    subscribeOn(Schedulers.io()).
    observeOn(AndroidSchedulers.mainThread()).
    subscribe(value -> updateUi(value), error -> handleError(error));

Having Single.just() here would not work since someIoOperation() would be executed on the current thread.

Algin answered 5/10, 2018 at 19:36 Comment(0)
U
58

In the use case you've mentioned, there is actually no major difference.

Now imagine we need the object to be created dynamically through a function call?

fun getTimeObject() {
    val timeInMillis = System.currentTimeMillis()
    return TimeObject(timeInMillis)
}

Then with, Single.just(getTimeObject()) the resulting Single will emit the same Long when it has a new subscriber.

However, with Single.fromcallable(()-> getTimeObject()), the resulting Single will emit a different Long indicating the current time in millis when it has a new subscriber.

That's because fromCallable executes it's lambda everytime it has a new subscriber Lazily.

Unnerve answered 5/10, 2018 at 18:50 Comment(1)
I found this example excellent, because it shows significant difference between these 2 functions in very short lines. Should be written into a textbook!Hexastyle
J
2

You should use fromCallable() when you have a function like

MyObject myFunction() {
    // some login here
    return new MyObject();
}

Then you can create Single from this function like this:

Single.fromCallable(() -> myFunction());

Single.just(myObject) just emits your object without any logic.

So there is no need to use fromCallable() when you want to emit specific item.

Justificatory answered 5/10, 2018 at 18:41 Comment(0)
C
2

In the documents they distinguished between two times Assemble time and Runtime;

Assembly time The preparation of dataflows by applying various intermediate operators

Runtime This is the state when the flows are actively emitting items

Simply Single.just() is evaluated in the Assembly time not after the main process is completed

Single.defer() and Single.fromcallable() evaluate the Single object in Runtime

Please check official documents code examples here

Cantilever answered 15/9, 2019 at 12:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.