Modifier la durée du timeout de Volley

192

J'utilise le nouveau framework Volley pour Android pour faire une requête à mon serveur. Mais il expire avant d'obtenir la réponse, bien qu'il réponde.

J'ai essayé d'ajouter ce code:

HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, timeoutMs);

dans HttpClientStackle framework Volley à un entier différent (50000), mais il expire toujours avant 50 secondes.

Existe-t-il un moyen de modifier le délai d'expiration en une valeur longue?

Cissmayazz
la source
Double possible: stackoverflow.com/questions/693997/…
Adam Stelmaszczyk
22
@AdamStelmaszczyk - ce ne serait pas un doublon car il s'agit de détails spécifiques dans le framework Volley. La question SO référencée concerne l'utilisation de la HttpClientclasse.
Michael Banzon

Réponses:

363

Voir Request.setRetryPolicy()et le constructeur pour DefaultRetryPolicy, par exemple

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));
larham1
la source
Savez-vous également comment définir la priorité d'une demande?
Markus
2
@Markus remplace Request.getPriority () pour renvoyer quelque chose d'autre que «normal». ImageRequest fait cela. REMARQUE: vous devriez le poser dans une question SO distincte.
larham1
1
C'est exactement ce que je cherchais pour empêcher Volley de rejeter ma requête qui prend 15 secondes. - Merci!
slott
Je viens de l'ajouter pour les demandes POST afin de désactiver la relance à l'expiration du délai. Il est incroyable que les développeurs Google aient décidé de définir une politique de nouvelle tentative sur les demandes POST. J'ai résolu mon problème. Merci.
Proverbio
1
@ Roon13 voir l'exemple de constructeur de requête qui vient d'être ajouté.
larham1
230

Pour gérer Android Volley Timeout, vous devez utiliser RetryPolicy

RetryPolicy

  • Volley fournit un moyen simple d'implémenter votre RetryPolicy pour vos demandes.
  • Volley définit Socket & ConnectionTImeout par défaut sur 5 secondes pour toutes les demandes.

RetryPolicy est une interface dans laquelle vous devez implémenter votre logique sur la façon dont vous souhaitez réessayer une demande particulière lorsqu'un délai d'expiration se produit.

Il traite de ces trois paramètres

  • Timeout - Spécifie le délai d'expiration du socket en millisecondes pour chaque nouvelle tentative.
  • Nombre de tentatives - Nombre de tentatives de relance.
  • Back Off Multiplier - Un multiplicateur qui est utilisé pour déterminer le temps exponentiel défini sur socket pour chaque nouvelle tentative.

Par ex. Si RetryPolicy est créé avec ces valeurs

Délai d'expiration - 3000 ms, nombre de tentatives - 2, multiplicateur d'arrêt - 2,0

Nouvelle tentative 1:

  • time = time + (time * Back Off Multiplier);
  • temps = 3000 + 6000 = 9000ms
  • Délai d'expiration du socket = temps;
  • Requête expédiée avec un délai d'expiration du socket de 9 secondes

Nouvelle tentative 2:

  • time = time + (time * Back Off Multiplier);
  • temps = 9000 + 18000 = 27000ms
  • Délai d'expiration du socket = temps;
  • Requête expédiée avec un délai d'expiration du socket de 27 secondes

Donc, à la fin de Retry Attempt 2, si le délai d'expiration du socket se produit, Volley jettera un TimeoutErrordans votre gestionnaire de réponse d'erreur d'interface utilisateur.

//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));
Yakiv Mospan
la source
Merci pour une réponse détaillée sur ce que RetryPolicyfait réellement l' implémentation.
dbm
5
Bonne réponse @Yakiv Mospan, mais sur votre exemple, l'heure de la première tentative est de 0 + (3000 * 2) au lieu de 3000 + (3000 * 2). Et le second 6000 + (3000 * 2).
13KZ
13KZ, je pense que vous vous trompez toujours en ce qui concerne les calculs de temps, consultez ma modification et vérifiez la source de la volée
Protongun
1
Juste un rappel pour les personnes qui l'utilisent: utilisez toujoursnew DefaultRetryPolicy( et assurez-vous de ne jamais réutiliser un RetryPolicyobjet, car l'objet est référencé tout au long du processus de demande, et des incréments de nouvelle tentative sont ajoutés sur la même valeur de délai d'expiration de l'objet, augmentant ainsi les délais d'expiration de vos futures demandes.
IG Pascual
comment est le délai d'expiration de la connexion?
Sam YC
23

Juste pour contribuer à mon approche. Comme déjà répondu, RetryPolicyc'est la voie à suivre. Mais si vous avez besoin d'une stratégie différente de celle par défaut pour toutes vos demandes, vous pouvez la définir dans une classe Request de base, vous n'avez donc pas besoin de définir la stratégie pour toutes les instances de vos demandes.

Quelque chose comme ça:

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

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

Dans mon cas, j'ai une GsonRequest qui s'étend à partir de cette BaseRequest, donc je ne cours pas le risque d'oublier de définir la politique pour une demande spécifique et vous pouvez toujours la remplacer si une demande spécifique l'exige.

Androiderson
la source
1
Cela devrait fonctionner correctement? setRetryPolicy (nouveau 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);
}
chavanNil
la source
7
req.setRetryPolicy(new DefaultRetryPolicy(
    MY_SOCKET_TIMEOUT_MS, 
    DefaultRetryPolicy.DEFAULT_MAX_RETRIES, 
    DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

Vous pouvez définir MY_SOCKET_TIMEOUT_MScomme 100. Ce que vous voulez définir est en millisecondes. DEFAULT_MAX_RETRIESpeut être 0 par défaut est 1.

Manasvi
la source
4
int MY_SOCKET_TIMEOUT_MS=500;

 stringRequest.setRetryPolicy(new DefaultRetryPolicy(
                MY_SOCKET_TIMEOUT_MS,
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
Avinash
la source
3

Une autre façon de le faire est d'utiliser JsonObjectRequest personnalisé en:

@Override
public RetryPolicy getRetryPolicy() {
    // here you can write a custom retry policy and return it
    return super.getRetryPolicy();
}

Source: exemple Android Volley

Sachez le
la source
2

Solution alternative si toutes les solutions ci-dessus ne fonctionnent pas pour vous

Par défaut, Volley définit le délai d'expiration de la même manière pour les deux setConnectionTimeout()et setReadTimeout()avec la valeur from RetryPolicy. Dans mon cas, Volleylève une exception de délai d'expiration pour un gros morceau de données, voir:

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

Ma solution est de créer une classe qui s'étend HttpStackavec ma propre setReadTimeout()politique. Ensuite, utilisez-le lors de la création RequestQueuecomme suit:

Volley.newRequestQueue(mContext.getApplicationContext(), new MyHurlStack())
Bao Le
la source
1

J'ai fini par ajouter une méthode setCurrentTimeout(int timeout)à RetryPolicyet sa mise en œuvre dans DefaultRetryPolicy.

Ensuite, j'ai ajouté un setCurrentTimeout(int timeout)dans la classe Request et l' ai appelé.

Cela semble faire le travail.

Désolé pour ma paresse au fait et hourra pour l'open source.

Cissmayazz
la source