我有一个组件A,它自己查询API并使用RX将结果存储在缓存中:
List<Data> cache = ...;
void queryData(int parameter) {
myApi.getData(parameter).subscribe(data => cache.add(data));
}
现在,我想从其他组件中查询此缓存。在缓存未命中时,我希望该设计允许重新使用机上订阅(如果存在)。这是为了避免重复相同的请求。
我正在考虑将Observable
存储在单独的缓存中(仍在我的组件A中)。
List<Observable<Data>> requestCache = ...;
public Observable<Data> getData(int parameter) {
// if cache contains data, return new observable that emits that item
// if cache does not contain data, check if requestCache contains the Observable I need. If so, return it.
// if all else fails, return queryData(parameter)
}
我需要将我原来的queryData
修改为:
Observable<Data> queryData(int parameter) {
Observable<Data> observable = myApi.getData(parameter);
requestCache.add(observable);
observable.subscribe(data => cache.add(data));
observable.subscribe(data => requestCache.remove(observable));
return observable;
}
这将完全隐藏这些请求到其他组件的缓存/飞行复杂性。但是,我想知道RX中是否有内置的方法来处理这个问题。
我是在正确的轨道上还是有更好的模式?
答案 0 :(得分:4)
没有内置的方法可以做到这一点。以下是我将如何解决这个问题:
public final class ReactiveCache<K, V> {
final Map<K, Observable<V>> requests = new HashMap<>();
final Function<K, Observable<V>> generator;
public ReactiveCache(Function<K, Observable<V>> generator) {
this.generator = generator;
}
public Observable<V> get(K key) {
ConnectableObservable<V> result;
synchronized (requests) {
Observable<V> current = requests.get(key);
if (current != null) {
return current;
}
result = generator.apply(key)
.doOnTerminate(() -> {
synchronized (requests) {
requests.remove(key);
}
})
.replay();
requests.put(key, result);
}
return result.autoConnect(0);
}
}
在这个类中,当你调用get()并且有一个正在进行中的observable时,你可以加入它并接收它的所有值。如果没有,或者飞行中已经完成,你将启动一个新的Observable。