Volley超时重试策略_RetryPolicy

基础知识

要弄明白超时重试策略首先明白两个异常信息:

  • java.net.SocketTimeoutException

    This exception is thrown when a timeout expired on a socket read or accept operation.
    

    当读取一个socket或者接受操作超时会抛出该异常,通俗讲就是响应超时。

  • org.apache.http.conn.ConnectTimeoutException

    A timeout while connecting to an HTTP server or waiting for an available connection from an HttpConnectionManager.
    

    当连接HTTP服务或者从HttpConnectionManager中得到一个可用的连接超时后抛出该异常,通俗讲就是请求超时。

个人对一次http请求的理解为以下三个阶段,一:建立连接;二:数据传送;三,断开连接;
当建立连接在规定的时间内(ConnectionTimeOut )没有完成,那么此次连接就结束,抛出ConnectTimeoutException后续的SocketTimeOutException就一定不会发生。
只有当连接建立起来后,也就是没有发生ConnectionTimeOutException ,才会开始传输数据,如果数据在规定的时间内(SocketTimeOut)传输完毕,则断开连接。否则,触发SocketTimeOutException

重试策略

Volley对超时重试策略的处理在BasicNetwork的performRequest()方法中,部分代码如下:

    //这里的while循环进行重试操作的,往下执行的操作中如果有正确返回值或者抛出异常,则该循环结束
    //一次请求只有发生SocketTimeoutException 或ConnectTimeoutException或认证失败的401、403错误才会进行重试策略
    public NetworkResponse performRequest(Request<?> request) throws VolleyError {
        long requestStart = SystemClock.elapsedRealtime();
        while (true) {
            HttpResponse httpResponse = null;
            byte[] responseContents = null;
            Map<String, String> responseHeaders = Collections.emptyMap();
            try {
                ........省略部分代码.........
                return response;

            } catch (SocketTimeoutException e) {
                attemptRetryOnException("socket", request, new TimeoutError());
            } catch (ConnectTimeoutException e) {
                attemptRetryOnException("connection", request, new TimeoutError());
            } catch (MalformedURLException e) {
                throw new RuntimeException("Bad URL " + request.getUrl(), e);
            } catch (IOException e) {
                int statusCode = 0;
                NetworkResponse networkResponse = null;
                if (httpResponse != null) {
                    statusCode = httpResponse.getStatusLine().getStatusCode();
                } else {
                    throw new NoConnectionError(e);
                }
                VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
                if (responseContents != null) {
                    networkResponse = new NetworkResponse(statusCode, responseContents,
                            responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
                    if (statusCode == HttpStatus.SC_UNAUTHORIZED ||
                            statusCode == HttpStatus.SC_FORBIDDEN) {
                        attemptRetryOnException("auth",
                                request, new AuthFailureError(networkResponse));
                    } else {
                        // TODO: Only throw ServerError for 5xx status codes.
                        throw new ServerError(networkResponse);
                    }
                } else {
                    throw new NetworkError(networkResponse);
                }
            }
        }
    }

attemptRetryOnException的代码如下:

    /**
     * Attempts to prepare the request for a retry. If there are no more attempts remaining in the
     * request's retry policy, a timeout exception is thrown.
     * @param request The request to use.
     */
    private static void attemptRetryOnException(String logPrefix, Request<?> request,
            VolleyError exception) throws VolleyError {
        RetryPolicy retryPolicy = request.getRetryPolicy();
        int oldTimeout = request.getTimeoutMs();

        try {
            retryPolicy.retry(exception);
        } catch (VolleyError e) {
            request.addMarker(
                    String.format("%s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout));
            throw e;
        }
        request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, oldTimeout));
    }

这段中如果执行retryPolicy.retry(exception);没有抛异常,则继续执行超时重试策略;在DefaultRetryPolicy的具体实现中:

    /**
     * Prepares for the next retry by applying a backoff to the timeout.
     * @param error The error code of the last attempt.
     */
    @Override
    public void retry(VolleyError error) throws VolleyError {
        mCurrentRetryCount++;
        mCurrentTimeoutMs += (mCurrentTimeoutMs * mBackoffMultiplier);
        if (!hasAttemptRemaining()) {
            throw error;
        }
    }

    /**
     * Returns true if this policy has attempts remaining, false otherwise.
     */
    protected boolean hasAttemptRemaining() {
        return mCurrentRetryCount <= mMaxNumRetries;
    }

从retry()方法中可以看出每次执行retry后,超时时间会增大,当重试次数大于mMaxNumRetries值后,抛出异常,结束该次请求;

小结:

DefaultRetryPolicy中的默认最大mMaxNumRetries为1,mCurrentTimeoutMs为2500毫秒,个人觉得超时时间有点短,可根据后台的业务处理所花费的时间对该值进行修改。在HttpClient的默认超时时间为10000毫秒,我们也可根据这个参考值设置默认超时时间为10000毫秒

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值