更改Volley超时时间的持续时间

205

我使用新的Android Volley框架向我的服务器发送请求。但是在获取响应之前它会超时,尽管它确实有响应。

我尝试添加以下代码:

HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, timeoutMs);
在Volley框架的HttpClientStack中将超时设置为不同的整数值(50000),但仍在50秒之前超时。有没有一种方法将超时时间更改为长时间值?

可能是重复问题:https://dev59.com/03RB5IYBdhLWcg3wLkxM - Adam Stelmaszczyk
24
@AdamStelmaszczyk - 这不是重复问题,因为它涉及Volley框架中的具体细节。引用的SO问题与HttpClient类的使用相关。 - Michael Banzon
9个回答

387

请参阅Request.setRetryPolicy()DefaultRetryPolicy的构造函数,例如。

JsonObjectRequest myRequest = new JsonObjectRequest(Method.GET,
        url, null,
        new Response.Listener<JSONObject>() {

            @Override
            public void onResponse(JSONObject response) {
                Log.d(TAG, response.toString());
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.d(TAG, "Error: " + error.getMessage());
            }
});

myRequest.setRetryPolicy(new DefaultRetryPolicy(
        MY_SOCKET_TIMEOUT_MS, 
        DefaultRetryPolicy.DEFAULT_MAX_RETRIES, 
        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

2
@Markus 重写 Request.getPriority() 方法,以返回除“normal”之外的其他内容。ImageRequest 已经实现了这一点。注意:你应该在一个单独的 SO 问题中提出这个问题。 - larham1
1
这正是我一直在寻找的,以防止Volley丢弃我的请求,该请求需要15秒钟。- 谢谢! - slott
我刚刚添加了这个功能,用于禁用POST请求的重试超时。谷歌开发人员决定在POST请求上设置重试策略是非常错误的。解决了我的问题。谢谢。 - Juampa
@larham1 我应该在哪里编写DefaultRetryPolicy构造函数?Volley.jar是已编译的类文件。我们不能编辑Request.class,对吧? - Roon13
1
@Roon13,请查看刚刚添加的示例请求构造器。 - larham1
显示剩余2条评论

243
要处理Android Volley超时,您需要使用RetryPolicyRetryPolicy是一个接口,您需要实现如何在超时发生时重试特定请求的逻辑。
它处理这三个参数:
- Timeout - 每次重试尝试的毫秒数Socket超时。
- Number Of Retries - 重试尝试的次数。
- Back Off Multiplier - 用于确定每次重试尝试时设置到套接字的指数时间的乘数。
例如,如果使用以下值创建RetryPolicy
Timeout-3000ms、Num-of-Retry-Attempts-2、Back-Off-Multiplier-2.0
重试尝试1:
- 时间=时间+(时间×Back Off Multiplier); - 时间=3000+6000 = 9000ms; - 套接字超时=time; - 发送具有9秒套接字超时的请求;
重试尝试2:
- 时间=时间+(时间×Back Off Multiplier); - 时间=9000+18000 = 27000ms; - 套接字超时=time; - 发送具有27秒套接字超时的请求;
因此,在第二次重试尝试结束时,如果仍然发生套接字超时,Volley将在UI错误响应处理程序中抛出TimeoutError
//Set a retry policy in case of SocketTimeout & ConnectionTimeout Exceptions. 
//Volley does retry for you if you have specified the policy.
jsonObjRequest.setRetryPolicy(new DefaultRetryPolicy(5000, 
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES, 
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

5
感谢 @Yakiv Mospan 提供的好答案。但是针对您提到的示例,第一次尝试的时间应为0 + (3000 * 2),而不是3000 + (3000 * 2)。第二次尝试的时间应为6000 + (3000 * 2)。 - 13KZ
13KZ,我认为你在时间计算方面仍然有误,请查看我的编辑并根据Volley源代码进行验证。 - Protongun
1
提醒使用此功能的人:始终使用new DefaultRetryPolicy(并确保永不重复使用RetryPolicy对象,因为该对象通过整个请求过程引用,并且重试增量添加到相同的对象超时值上,从而使您未来的请求超时无限增长。 - I.G. Pascual
连接握手超时时间是多少? - Sam YC

23

仅仅是为了提供我的方法。如已经回答的那样,RetryPolicy就是正确的解决方法。但如果您需要一个不同于所有请求的默认策略的策略,则可以在基础请求类中设置它,这样您就不需要为所有请求实例设置该策略。

像这样:

public class BaseRequest<T> extends Request<T> {

    public BaseRequest(int method, String url, Response.ErrorListener listener) {
        super(method, url, listener);
        setRetryPolicy(getMyOwnDefaultRetryPolicy());
    }
}

在我的情况下,我有一个继承自BaseRequest的GsonRequest,因此我不会忘记为特定请求设置策略的风险,并且如果某个特定请求需要覆盖它,您仍然可以进行覆盖。


1
这应该可以运行,对吧? setRetryPolicy(new DefaultRetryPolicy( 1000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); - LOG_TAG

12
/**
 * @param request
 * @param <T>
 */
public <T> void addToRequestQueue(Request<T> request) {

    request.setRetryPolicy(new DefaultRetryPolicy(
            MY_SOCKET_TIMEOUT_MS,
            DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

    getRequestQueue().add(request);
}

5
req.setRetryPolicy(new DefaultRetryPolicy(
    MY_SOCKET_TIMEOUT_MS, 
    DefaultRetryPolicy.DEFAULT_MAX_RETRIES, 
    DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

您可以将MY_SOCKET_TIMEOUT_MS设置为100。您想要设置的任何值都是以毫秒为单位的。DEFAULT_MAX_RETRIES可以是0,默认值为1。

5
int MY_SOCKET_TIMEOUT_MS=500;

 stringRequest.setRetryPolicy(new DefaultRetryPolicy(
                MY_SOCKET_TIMEOUT_MS,
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

3
通过自定义的JsonObjectRequest实现也是一种方法,具体操作如下:
@Override
public RetryPolicy getRetryPolicy() {
    // here you can write a custom retry policy and return it
    return super.getRetryPolicy();
}

来源:Android Volley示例


2

如果以上所有解决方案都无法解决您的问题,可以尝试以下备选方案:

Volley默认将setConnectionTimeout()setReadTimeout()的超时时间设置为相同,并使用RetryPolicy中的值。在我的情况下,Volley在处理大数据块时会抛出超时异常,请参考:

com.android.volley.toolbox.HurlStack.openConnection(). 

我的解决方案是创建一个继承了HttpStack的类,并使用自己的setReadTimeout()策略。然后在创建RequestQueue时使用它,如下所示:

Volley.newRequestQueue(mContext.getApplicationContext(), new MyHurlStack())

1
我最终添加了一个方法setCurrentTimeout(int timeout)RetryPolicy和它在DefaultRetryPolicy中的实现。
然后我在Request类中添加了一个setCurrentTimeout(int timeout)并调用了它。
看起来这样做可以完成工作。
顺便说一下,对于我的懒惰感到抱歉,同时也为开源欢呼。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接