Search code examples
rx-javareactive-programmingrx-java2reactivex

How to make a cold Single 'hot' in RxJava


I have some code that makes network requests and returns a Single for each.

public Single<Response> getSomeData(String endpoint)    
{
    return Single.fromCallable(makeNewRequest(endpoint));
}

This works as long as the caller actually subscribes() to the returned Single. However in some specific cases (for POST requests), the caller is not interested in the result, and never calls subscribe().

Since fromCallable() defers execution until subscription time, this means the request will not actually be executed.

Question: What is the proper (idiomatic) way to turn this (cold) Single into a hot one, so that the network request is executed right away, regardless of whether the caller calls subscribe() ?


Solution

  • I have finally solved this by using Single.cache() and subscribing a dummy observer. This way the request is executed regardless of whether the API client actually subscribes to the returned observable. The code looks like this:

    public Single<Response> getSomeData(String endpoint)    
    {
        Single<Response> res = Single.fromCallable(makeNewRequest(endpoint))
            .subscribeOn(Schedulers.io()) // if needed
            .cache();
        res.subscribe(dummyObserver);
        return res;
    }
    
    private static final SingleObserver<Response> dummyObserver = new SingleObserver<Response>() {
        public void onSubscribe(Disposable d) { }
        public void onSuccess(Response s) { }
        public void onError(Throwable e) { }
    };
    

    Update:

    Here's another approach that does not need the dummy observer object:

    public Single<Response> getSomeData(String endpoint)    
    {
        Single<Response> res = Single.fromCallable(makeNewRequest(endpoint))
            .subscribeOn(Schedulers.io()); // if needed
    
        SingleSubject subject = SingleSubject.create(); 
        res.subscribe(subject);
        return subject;
    }