API를 자체적으로 쿼리하고 RX를 사용하여 캐시에 결과를 저장하는 구성 요소 A가 있습니다.
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에 이것을 처리하는 내장 방법이 있는지 궁금합니다.
내가 올바른 길을 가고 있는가 아니면 더 나은 패턴이 있는가?
이를 수행하는 기본 제공 방법은 없습니다. 이 문제를 해결하는 방법은 다음과 같습니다.
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이 시작됩니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다