有时请求失败,如果不是由于客户端错误(即:不是4xx),那么我想重试发送相同的请求。
我的所有请求都有一个请求ID标头,当我再次发送某个请求(重试)时,我需要发送与第一个使用的id相同的id。
这听起来很简单,但事实证明使用Retrofit 2很难完成,除非我当然错过了什么。
我的所有请求都是异步的,所以在回调中,如果我需要重试我这样做:
public void onResponse(final Call<T> call, final Response<T> response) {
if (response.isSuccessful()) {
handleResponse(response);
} else if (response.code() >= 400 && response.code() < 500) {
handleClientError(response);
} else {
call.clone().enqueue(this);
}
}
我还有一个拦截器,用于为所有请求添加标头:
new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
final Request request = chain.request();
final Request.Builder newRequestBuilder = request.newBuilder()
.addHeader("Header1-name", "Header1-value")
.addHeader("Header2-name", "Header2-value")
...
.addHeader("HeaderN-name", "HeaderN-value");
if (request.header("REQUEST-ID") == null) {
newRequestBuilder.addHeader("REQUEST-ID", UUID.randomUUID().toString());
}
return chain.proceed(newRequestBuilder.build());
}
};
我认为,因为我克隆了Call
,然后(重试)请求将包含前一个请求的标题,但情况并非如此(可能是因为{{1}克隆而不是Call
)。
我的问题是我无法识别请求或致电我的Request
,因此我无法维护请求/致电ID的地图。
还没有办法向呼叫/请求添加信息(因为它们不是由我生成的,而且缺少和设置这样的情况)。
我想也许我可以使用Interceptor.intercept
方法,但是我再也无法控制在那里分配的对象实例,并且请求之间的对象不同。
如果我们已经讨论过这个问题,那么这个标签到底是什么?我无法找到有关它的文档。
知道我怎么能以某种方式解决这个问题? 感谢
答案 0 :(得分:0)
我采用了另一种方法,而不是使用网络拦截器和回调,我编写了一个使用网络拦截器的解决方案:
class BackoffRetryInteceptor implements Interceptor {
private static final long RETRY_INITIAL_DELAY = 500;
private static final long RETRY_MAX_DELAY = 35000;
@Override
public Response intercept(final Chain chain) throws IOException {
Request request = chain.request();
final Headers.Builder headersBuilder = new Headers.Builder();
addHeaders(headersBuilder);
final Headers headers = headersBuilder.build();
long delay = RETRY_INITIAL_DELAY;
Response response = null;
IOException exception = null;
while (delay < RETRY_MAX_DELAY) {
exception = null;
request = request.newBuilder().headers(headers).build();
try {
response = chain.proceed(request);
if (response.isSuccessful() || response.code() != 500) {
return response;
}
} catch (IOException e) {
exception = e;
}
try {
Thread.sleep(delay);
delay *= 2;
} catch (InterruptedException e) {
delay = RETRY_MAX_DELAY;
}
}
if (exception != null) {
throw exception;
}
return response;
}
private static void addHeaders(final Headers.Builder headers) {
headers.add("Header1-name", "Header1-value")
.add("Header2-name", "Header2-value")
...
.add("HeaderN-name", "HeaderN-value")
.add("Request-Id", UUID.randomUUID().toString());
}
}
这似乎在我的测试中运作良好 但主要的问题是阻塞了网络线程。
如果有人能想出更好的解决方案,我很乐意听到它。