我正在尝试使用 rxJava 实现此工作流程,但我确定我是否误用或做错了事情。
- 用户要求登录
- 如果登录结果在缓存中可用,则“发出”缓存的登录结果
- 否则,如果一切成功,则实际执行对 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,所以我不确定我的实现。
感谢您的时间。
我认为这段代码没问题,干得好:)
你使用是正确的Observable.create
在你的LoginTask
因为否则调用结果可以在内部缓存,然后retry
没有多大帮助...
我认为这对于CachedLoginResult
's Observable
。在这里您可以使用以下方法简化代码Observable.just
and Observable.error
实用方法,例如:
public Observable<LoginResult> getObservable() {
if (hasCache()) {
return Observable.just(lr);
} else {
return Observable.error(new RuntimeException("No cache"));
}
}
Note: just
存储您告诉它在内部发出的值,以便重新订阅将始终产生该值。这就是我上面暗示的,你不应该这样做Observable.just(performRequest()).retry(3)
例如,因为performRequest
只会被调用一次。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)