我的目标是执行网络呼叫的方法,除非网络呼叫已在进行中,在这种情况下呼叫者订阅现有呼叫的结果。
这是我拥有的,它主要起作用:
private AsyncSubject<Stuff> asyncSubject;
public Observable<Stuff> getStuff() {
if (asyncSubject == null) {
asyncSubject = AsyncSubject.create();
asyncSubject
.doAfterTerminate(new Action() {
@Override
public void run() throws Exception {
asyncSubject = null;
}
})
.subscribe();
retrofitApi.getStuff()
.subscribe(asyncSubject);
}
return asyncSubject
.someOperatorsHere();
}
这主要起作用,因为asyncSubject在终止时将其自身空出,以便任何后续调用将重新执行网络请求。
但是有一个错误,if (asyncSubject == null)
和return asyncSubject
之间有一个窗口,其中doAfterTerminate可以执行,我得到一个空指针。
任何想法如何修复错误。也许有更优雅的Rx方式来做到这一点?或synchronized
阻止。或者是一种查询Retrofit网络进度的方法。
答案 0 :(得分:2)
有几种可能的解决方案,我只想描述一下你的情况可能最简单的解决方案。
你有2个问题:竞争条件,以及取消和重新创建主题,这是相当不安全的。
您可以将retrofitApi.getStuff().subscribe(asyncSubject);
保存在此处
if (asyncSubject == null)
而不是检查if (s.isUnsubscribed())
,您可以检查private AsyncSubject<Stuff> asyncSubject = AsyncSubject.create();
private Subscription subscription = Subscriptions.unsubscribed();
public Observable<Stuff> getStuff() {
if (subscription.isUnsubscribed()) {
subscription = retrofitApi.getStuff()
.subscribe(asyncSubject);
}
return asyncSubject
.someOperatorsHere();
}
。
所以你的代码看起来或多或少会像这样:
{{1}}
答案 1 :(得分:1)
此解决方案在正在进行的订阅者之间共享订阅。
private Observable<Stuff> stuff = retrofitApi.getStuff().share();
public Observable<Stuff> getStuff() {
return stuff
.someOperatorsHere();
}