重试

时间:2017-01-09 05:18:03

标签: java rx-java rx-android

我每次打开页面时都会调用Observable<FeaturedItemList> getFeatured()。从同一页面上的两个不同组件调用此函数。由于它从网络中检索,我将其缓存并使其与ReplaySubject共享。

public Observable<FeaturedItemList> getFeatured() {
    if(mFeaturedReplaySubject == null) {
        mFeaturedReplaySubject = ReplaySubject.create();
        getFromNetwork().subscribe(mFeaturedReplaySubject);
    }

    return mFeaturedReplaySubject;
}

然后我意识到当请求因某些原因失败时,如果用户回到该页面,除非用户杀死了应用程序,否则它不会显示任何结果。所以我决定采用一些重试逻辑。这是我的所作所为:

public Observable<FeaturedItemList> getFeatured() {
    synchronized (this) {
        if (mFeaturedReplaySubject == null) {
            mFeaturedReplaySubject = ReplaySubject.create();
            getFromNetwork().subscribe(mFeaturedReplaySubject);

            return mFeaturedReplaySubject;
        } else {
            return mFeaturedReplaySubject.onErrorResumeNext(throwable -> {
                mFeaturedReplaySubject = null;
                return getFeatured();
            });
        }
    }
}

虽然这有效,但我担心我在这里做的事情并不好,因为这种方法不会涵盖这种情况。 有没有更好的方法?

另外,为了使用主题共享可观察对象,我在某处阅读了connect()publish()share(),但我不知道如何使用它。

1 个答案:

答案 0 :(得分:0)

代码

private Observable<FeaturedItemList> mFeatured =
    // initialized on construction
    getFromNetwork()
        .retry(3) // number of times to retry
        .cache();

public Observable<FeaturedItemList> getFeatured() {
    return mFeatured;
}

说明

网络来源

您的getFromNetwork()函数将返回常规的observable,它应该在每次订阅时访问网络。 调用时不应访问网络。例如:

Future<FeaturedItemList> makeAsyncNetworkRequest() {
    ... initiate network request here ...
}

Observable<FeaturedItemList> getFromNetwork() {
    return Observable.fromCallable(this::makeAsyncNetworkRequest)
        .flatMap(Observable::fromFuture);
}

<强>重试

有一个.retryXxx()运算符系列,仅在出错时激活。他们要么根据各种条件重新订阅源代码,要么传递错误。 如果没有错误,这些操作员什么都不做。我在我的例子中使用了简单的retry(count),它会毫不拖延地重试指定的次数。您可以使用retryWhen()添加延迟或任何复杂的逻辑(例如,请参阅herehere)。

<强>缓存

cache()运算符记录事件序列并将其重播给所有新订阅者。不好的是它不可刷新。它永远存储上游的结果,无论是成功还是错误,再也不会重试。

替代cache()

replay().refCount()将事件重播给所有现有订阅者,但只要所有订阅者都取消订阅(或完成),就会忘记所有订阅者。当新订户到达时,它会重新订阅getFromNetwork()(当然会重试错误)。

提及但不需要的运营商

share()publish().refCount()的简写。它允许多个并发订户共享单个订阅,即对subscribe()进行单个呼叫,而不是为每个订户执行此操作。 cache()replay().refCount()都包含相同的功能。