我经常遇到一种模式,但我不太确定如何有效地解决它。 基本上,如果我有一个Observable持有一个昂贵的项目T,我不希望每次使用它时都重新构建该T项目,或者将其映射到数千个不同的其他observable中,这将导致它被构建1000次。
因此,我开始使用replay()将其缓存一段时间,但理想情况下,我希望在发射空闲一段时间后清除缓存。 有没有运算符或某个转换器可以实现这一点?
因此,我开始使用replay()将其缓存一段时间,但理想情况下,我希望在发射空闲一段时间后清除缓存。 有没有运算符或某个转换器可以实现这一点?
public final class ActionManager {
private final Observable<ImmutableList<Action>> actionMap;
private ActionManager() {
this.actionMap = Observable.defer(() -> buildExpensiveList()).replay(10, TimeUnit.SECONDS).autoConnect();
}
//this method could get called thousands of times
//I don't want to rebuild the map for every call
public Observable<Action> forItem(Item item) {
actionMap.map(l -> //get Action for item);
}
}
更新
尝试将此实现到Transformer / Operator组合中。这里有什么我做错了吗?
public static <T> Transformer<T,T> recacheOnIdle(long time, TimeUnit timeUnit) {
return obs -> obs.timeout(time, timeUnit).lift(new Operator<T,T>() {
private volatile T cachedItem;
private volatile boolean isCurrent = false;
@Override
public Subscriber<? super T> call(Subscriber<? super T> s) {
return new Subscriber<T>(s) {
@Override
public void onCompleted() {
if(!s.isUnsubscribed()) {
s.onCompleted();
}
}
@Override
public void onError(Throwable e) {
if(!s.isUnsubscribed()) {
if (e instanceof TimeoutException) {
isCurrent = false;
cachedItem = null;
} else {
s.onError(e);
}
}
}
@Override
public void onNext(T t) {
if(!s.isUnsubscribed()) {
if (!isCurrent) {
cachedItem = t;
}
s.onNext(cachedItem);
}
}
};
}
});
}