我正在尝试快速返回一个缓存observable,然后在完成后更新UI的网络请求。
使用Rx startWith,如果手机处于信号状态,则工作正常,但是如果我将手机置于飞行模式,那么改装网络调用就会很快失败onError,从startWith返回的缓存值永远不会被返回,因为onError终止了observable立即。我还需要知道observable是否抛出onError以显示给用户。我的缓存几乎是即时的,所以我宁愿在尝试任何网络调用之前返回缓存。有办法整齐地做到这一点吗?还是更好的方法呢?
public Observable<String> getMyString(String key){
WebRequestDbEntity myCachedString = mCache.getWebRequest(key);
String cachedString = myCachedString.getValue();
return retrofitWebDataStore().getMyString(key)
.startWith(Observable.just(cachedString))
.map(networkString -> {
mCache.saveRequest(key, networkString);
return networkString;
});
}
在表示层中:
getMyString(key)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onSuccess, this::onError);
答案 0 :(得分:1)
观察observable时...使用observeOn(AndroidSchedulers.mainThread,true)。真实的是延迟错误。这允许缓存observable在网络observable抛出错误之前返回。
getMyString(key)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread(), true)
.subscribe(this::onSuccess, this::onError);
答案 1 :(得分:0)
你可能需要考虑使用concat(),将缓存作为第一个Observable,这样你就可以确保在启动网络Observable之前返回缓存结果(如果有的话)。像这样的东西:
Observable<String> cacheObservable = Observable.fromCallable(() -> {
WebRequestDbEntity myCachedString = mCache.getWebRequest(key);
return myCachedString.getValue();
});
Observable<String> serverObservable =
retrofitWebDataStore().getMyString(key)
.doOnNext(networkString -> mCache.saveRequest(key, networkString));
return Observable.concat(cacheObservable, serverObservable);
这样,你确保返回第一个缓存对象(你的示例中没有处理任何缓存情况,但是它可以通过检查没有缓存结果和过滤来轻松解决,因此缓存Observable要么返回结果,要么只是完全没有任何东西),你将首先在表示逻辑中处理它。之后,网络请求将启动,如果你得到结果,你将把它保存到doOnNext()
的缓存中(在你的例子中你也用缓存的结果做了,不确定这是不是你想要的),而且只有错误可能是由网络请求引起的,但不会使缓存不返回值,因为它在缓存提取后发生。