在使用Volley作为网络请求框架的时候,遇到过一个问题,就是在自己的框架中发现打印的日志只有请求一次,但在服务端捕捉到的请求却是发送了2次。
本文参考自 Volley默认请求多次原因解析
1.volley的请求顺序
volley的请求主要都是调用BasicNetwork
里面的performRequest
方法获取服务器的响应。
大致的过程是:
- 添加header参数到request中
- 发送http
- 解析response
- 返回
主要要注意的是:这个请求的过程是循环的,直到得到服务器的响应或者抛出异常。这也就能解释为什么会在请求明明只发送一次却在服务端查看的时候是调用了2次的情况。
2.解决方法
volley还有一个方法getRetryPolicy
就是设置请求超时的时间和超时重复请求的次数
@Override
public RetryPolicy getRetryPolicy() {
RetryPolicy retryPolicy = new DefaultRetryPolicy(50 * 1000,0,0f);
return retryPolicy;
}
其中DefaultRetryPolicy
是一个默认的超时设置对象
- 参数一
DEFAULT_TIMEOUT_MS
是超时时间,时间应该设置的稍微大一点 - 参数二
DEFAULT_MAX_RETRIES
,超时后重复请求的次数,如果不希望有2次请求的情况,则设置为0 - 参数三
DEFAULT_BACKOFF_MULT
是backoff因子,对于请求失败之后的请求,并不会隔相同的时间去请求Server,不会以线性的时间增长去请求,而是一个曲线增长,一次比一次长,如果backoff因子是2,当前超时为3,即下次再请求隔6S。
下面是我自己实现的,对于JSONObjectRequest请求的一个封装请求
public class BasicRequest extends JsonObjectRequest{
public BasicAPI basicAPI;
public BasicRequest(BasicAPI basicAPI,Response.Listener<JSONObject> successListener,
Response.ErrorListener errorListener ){
super(basicAPI.getHttpType(), basicAPI.getUrl(),null, successListener, errorListener);
LogUtils.e("[url]"+basicAPI.getUrl());
this.basicAPI = basicAPI;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return basicAPI.getHeaders();
}
@Override
public byte[] getBody() {
return basicAPI.getBody();
}
/**
* 重写parseNetworkResponse方法,将返回的数据格式化位UTF-8
*
* @param response
* @return
*/
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String je = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
String temp = new String(response.data, basicAPI.getParamsEncoding());
return Response.success(new JSONObject(temp), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException var3) {
return Response.error(new ParseError(var3));
} catch (JSONException var4) {
return Response.error(new ParseError(var4));
}
}
@Override
public String getBodyContentType() {
if (StringUtils.isNoEmpty(basicAPI.getDiyBodyContentType())) {
return basicAPI.getDiyBodyContentType();
}
return super.getBodyContentType();
}
@Override
public RetryPolicy getRetryPolicy() {
RetryPolicy retryPolicy = new DefaultRetryPolicy(50 * 1000,0,0f);
return retryPolicy;
}
}
但是针对以上这种写法,还是会发现存在2次请求的情况。不知道是不是复写的方法getRetryPolicy
没有被调用还是怎样。有知道烦请告知一二。
这里做一点改进。在将请求添加到请求队列之前,再显式得设置retryPolicy
这个属性。即
basicRequest.setRetryPolicy(new DefaultRetryPolicy(50 * 1000,0,0f));
App.getRequestQueue().add(basicRequest);