RXJava的缓存处理 [英] Cache handling with RXJava
问题描述
我正在尝试使用rxJava来实现此工作流,但是我确定自己是否滥用或做错了事情.
I'm trying to implement this workflow with rxJava but i'm sure if i'm misusing or doing stuff wrong.
- 用户要求登录
- 如果缓存中有loginResult,则发出"缓存的LoginResult
- 否则,如果一切成功,则实际上执行对Web服务的请求并缓存结果
- 如果发生错误,请最多重试3次,如果是第4次,则清除高速缓存.
这是我的完整代码段.
public class LoginTask extends BaseBackground<LoginResult> {
private static CachedLoginResult cachedLoginResult = new CachedLoginResult();
private XMLRPCClient xmlrpcClient;
private UserCredentialsHolder userCredentialsHolder;
@Inject
public LoginTask(XMLRPCClient client, UserCredentialsHolder userCredentialsHolder) {
this.xmlrpcClient = client;
this.userCredentialsHolder = userCredentialsHolder;
}
@Override
public LoginResult performRequest() throws Exception {
return UserApi.login(
xmlrpcClient,
userCredentialsHolder.getUserName(),
userCredentialsHolder.getPlainPassword());
}
@Override
public Observable<LoginResult> getObservable() {
return cachedLoginResult.getObservable()
.onErrorResumeNext(
Observable.create(
((Observable.OnSubscribe<LoginResult>) subscriber -> {
try {
if (!subscriber.isUnsubscribed()) {
subscriber.onNext(performRequest()); // actually performRequest
}
subscriber.onCompleted();
} catch (Exception e) {
subscriber.onError(e);
}
})
)
.doOnNext(cachedLoginResult::setLoginResult)
.retry((attempts, t) -> attempts < 3)
.doOnError(throwable -> cachedLoginResult.purgeCache())
);
}
private static class CachedLoginResult {
private LoginResult lr = null;
private long when = 0;
private CachedLoginResult() {
}
public boolean hasCache() {
return lr != null && when + TimeUnit.MILLISECONDS.convert(30, TimeUnit.MINUTES) > System.currentTimeMillis();
}
public void setLoginResult(LoginResult lr) {
if (lr != null) {
this.lr = lr;
this.when = System.currentTimeMillis();
}
}
public void purgeCache() {
this.lr = null;
this.when = 0;
}
public Observable<LoginResult> getObservable() {
return Observable.create(new Observable.OnSubscribe<LoginResult>() {
@Override
public void call(Subscriber<? super LoginResult> subscriber) {
if (!subscriber.isUnsubscribed()) {
if (hasCache()) {
subscriber.onNext(lr);
subscriber.onCompleted();
} else {
subscriber.onError(new RuntimeException("No cache"));
}
}
}
});
}
}
}
由于我无法找到任何类似的示例,而就在1天前我开始使用rxjava进行游戏,所以我不确定我的实现.
Since i wan't able to find any similar examples and i started "playing" with rxjava just 1 day ago i'm unsure of my implementation.
谢谢您的时间.
推荐答案
我认为这段代码还不错,不错:)
I think this code is alright, good job :)
您正确地在 LoginTask
中使用 Observable.create
,因为否则调用的结果可以在内部缓存,然后 retry
帮不上忙...
You were right to use Observable.create
in your LoginTask
because otherwise result of the call could be cached internally, and then retry
wouldn't help much...
对于 CachedLoginResult
的 Observable
,我认为这是不必要的.在这里,您可以使用 Observable.just
和 Observable.error
实用程序方法来简化代码,例如:
This is I think however unnecessary for the CachedLoginResult
's Observable
. Here you can simplify your code by using Observable.just
and Observable.error
utility methods, something like:
public Observable<LoginResult> getObservable() {
if (hasCache()) {
return Observable.just(lr);
} else {
return Observable.error(new RuntimeException("No cache"));
}
}
注意: just
存储您告诉它在内部发出的值,以便重新订阅将始终产生该值.这就是我上面所暗示的,例如,您不应执行 Observable.just(performRequest()).retry(3)
,因为 performRequest
仅会被调用一次.
Note: just
stores the value you tell it to emit internally, so that resubscriptions will always produce this value. This is what I hinted above, you shouldn't do Observable.just(performRequest()).retry(3)
for example, because the performRequest
will only ever be called once.
这篇关于RXJava的缓存处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!