我有以下场景:我有一个我的应用程序感兴趣的名为 Foo
的对象。这个 Foo
对象来自远程服务,我想在本地缓存此实例并继续使用它,直到经过一定时间。
到目前为止,我已经尝试创建一个 FooState
类,其中包含 Foo
的实例以及指示 Foo
时间的时间戳以毫秒为单位获取:
public class FooState {
private Foo foo;
private long timestamp;
/* Constructor and getters */
}
现在,到目前为止,我已经想出了这段使用 concat 的代码:
public Observable<Foo> foo() {
return Observable.concat(local(), remote())
.takeFirst(fooState -> fooState.getTimestamp() >= System.currentTimeMillis())
.map(fooState -> fooState.getFoo())
.defaultIfEmpty(new Foo());
}
private Observable<FooState> local() {
return Observable.just(cache.hasFooState() ? cache.getFooState() : new FooState(null, 0));
}
private Observable<FooState> remote() {
return api.getFoo()
.map(foo -> new FooState(foo, System.currentTimeMillis() + ONE_DAY_MILLIS)
.doOnNext(fooState -> {
cache.save(fooState);
});
}
基本上,如果有缓存值,只要时间戳未过期,我就想使用它。如果时间戳过期或者没有缓存值,我想从远程服务中获取并缓存结果。
有没有更简洁的方法来实现这个用例?我是 RxJava 的新手,我想知道是否有任何 Rx 大师知道处理这种情况的更好方法。
最佳答案
您还可以使用内置的 .timestamp() 运算符和 Timestamped
BehaviorSubject<Timestamped<Foo>> subject = BehaviorSubject.create();
Observable<Foo> serviceCall() {
return subject.filter(new Func1<Timestamped<Foo>, Boolean>() {
@Override
public Boolean call(Timestamped<Foo> tsFoo) {
return tsFoo.getTimestampMillis() < expiry;
}
}).switchIfEmpty(serviceCall().timestamp().doOnNext(new Action1<Timestamped<Foo>>() {
@Override
public void call(Timestamped<Foo> tsFoo) {
subject.onNext(tsFoo);
}
})
.map(new Func1<Timestamped<Object>, Foo>() {
@Override
public Foo call(Timestamped<Object> tsFoo) {
return tsFoo.getValue();
}
});
}
关于java - RxJava : Read from cache until timestamp is expired,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47899554/