我每次打开页面时都会调用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()
,但我不知道如何使用它。
答案 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()
添加延迟或任何复杂的逻辑(例如,请参阅here和here)。
<强>缓存强>
cache()
运算符记录事件序列并将其重播给所有新订阅者。不好的是它不可刷新。它永远存储上游的结果,无论是成功还是错误,再也不会重试。
替代cache()
replay().refCount()
将事件重播给所有现有订阅者,但只要所有订阅者都取消订阅(或完成),就会忘记所有订阅者。当新订户到达时,它会重新订阅getFromNetwork()
(当然会重试错误)。
提及但不需要的运营商
share()
是publish().refCount()
的简写。它允许多个并发订户共享单个订阅,即对subscribe()
进行单个呼叫,而不是为每个订户执行此操作。 cache()
和replay().refCount()
都包含相同的功能。