如果使用RxJava 2

时间:2017-06-07 00:34:37

标签: java android retrofit rx-java

我的目标是执行网络呼叫的方法,除非网络呼叫已在进行中,在这种情况下呼叫者订阅现有呼叫的结果。

这是我拥有的,它主要起作用:

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网络进度的方法。

2 个答案:

答案 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();
}