alc*_*arv 5 java android java-8 rx-java retrofit
我在Android应用程序中使用Retrofit和RxJava进行通信,并且必须处理从似乎正常的HTTP响应(状态200代码)解析响应时出错.
我还实现了一种使用retryWhen运算符处理错误的方法,该运算符连接到用户的输入以决定是否重试.这是通过重新订阅原始作品Observable.
我尝试的第一种方法是这样的:
services.getSomething()
.map(response -> {
if (checkBadResponse(response)) {
throw new RuntimeException("Error on service");
} else {
return parseResponse(response);
}
}).retryWhen(this::shouldRetry);
Run Code Online (Sandbox Code Playgroud)
有了这个,服务不会再被调用.似乎retryWhen运营商无法重新订阅该服务Observable.
最终工作的是实现另一个运算符,它不发送onCompleted前进并使用它,lift如下所示:
public class CheckResponseStatus<T> implements Observable.Operator<ResponsePayload<T>, ResponsePayload<T>> {
@Override
public Subscriber<? super ResponsePayload<T>> call(Subscriber<? super ResponsePayload<T>> subscriber) {
return new Subscriber<ResponsePayload<T>>() {
private boolean hasError = false;
@Override
public void onCompleted() {
if (!hasError)
subscriber.onCompleted();
}
@Override
public void onError(Throwable e) {
hasError = true;
subscriber.onError(e);
}
@Override
public void onNext(ResponsePayload<T> response) {
if (response.isOk()) {
subscriber.onNext(response);
} else {
hasError = true;
subscriber.onError(new RuntimeException(response.getMessage()));
}
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
使用它像:
services.getSomething()
.lift(new CheckResponseStatus())
.map(response -> parseResponse(response))
.retryWhen(this::shouldRetry);
Run Code Online (Sandbox Code Playgroud)
这是处理它的正确方法还是有更简单,更好的方法?
这看起来像是rx-java实施中的一个错误。无论如何,从函数中抛出异常map是一件坏事,因为函数应该是纯粹的(例如没有副作用)。您应该在您的情况下使用flatMap运算符:
services.getSomething()
.flatMap(response -> {
if (checkBadResponse(response)) {
return Observable.<ResponseType>error(new RuntimeException("Error on service"));
} else {
return Observable.<ResponseType>just(parseResponse(response);
}
}).retryWhen(this::shouldRetry);
Run Code Online (Sandbox Code Playgroud)
上面的代码按预期工作,并且在发生错误时确实重试请求。
| 归档时间: |
|
| 查看次数: |
1533 次 |
| 最近记录: |