我有一些代码可以发出网络请求,并为每个请求返回一个Single
。
public Single<Response> getSomeData(String endpoint)
{
return Single.fromCallable(makeNewRequest(endpoint));
}
只要调用者实际上subscribes()
到返回的Single
,此方法就起作用。但是,在某些特定情况下(对于POST请求),调用者对结果不感兴趣,并且从不调用subscribe()
。
由于fromCallable()
将执行推迟到订阅时间之前,这意味着该请求将不会被实际执行。
问题:将这个{冷} Single
变成热点的正确方法是什么(惯用的)方法,以便无论呼叫者是否呼叫subscribe()
都立即执行网络请求?
答案 0 :(得分:2)
我想说您需要将publish
运算符与connect
结合使用。在此之前,您需要使用toObservable()
Single
转换为Observable
另外,请注意,如果呼叫者对实际结果不感兴趣,则Completable
套件可能会更好。您可以使用Single
Completable
转换为toCompletable()
答案 1 :(得分:1)
您可以使用SingleSubject
来为任何感兴趣的参与者缓存响应,但是请注意,您必须以某种方式向此API调用添加调度和可能的取消:
public Single<Response> getSomeData(String endpoint,
Scheduler scheduler, Consumer<? super Disposable> dispose) {
Callable<Response> requestor = makeNewRequest(endpoint);
SingleSubject<Response> result = SingleSubject.create();
Disposable d = scheduler.scheduleDirect(() -> {
try {
result.onSuccess(requestor.call());
} catch (Exception ex) {
result.onError(ex);
}
});
if (dispose != null) {
dispose.accept(d);
}
return result;
}
请注意,尽管此设置现在确实很热,但您必须再次调用getSomeData()
才能向同一端点发出新请求并获得新结果。
答案 2 :(得分:1)
我终于通过使用Single.cache()
并订阅了一个虚拟观察者来解决了这个问题。这样,无论API客户端是否实际订阅了返回的observable,都将执行请求。代码如下:
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) { }
};
更新:
这是不需要虚拟观察者对象的另一种方法:
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;
}