Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android volley DefaultRetryPolicy do not work as intended

So, I have this Volley PUT request:

private boolean syncCall(JSONObject jsonObject, final VolleyCallback
        callback) {

    final ProgressDialog progDailog = new ProgressDialog(context);

    final Boolean[] success = {false};

    progDailog.setMessage("...");
    progDailog.setIndeterminate(false);
    progDailog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

    progDailog.setCancelable(false);
    progDailog.show();

    final SharedPreferences prefs = PreferenceManager
            .getDefaultSharedPreferences(context);

    RequestQueue queue = Volley.newRequestQueue(context, new HurlStack());

    final String token = prefs.getString("token", null);

    String URL = Constants.getUrlSync();
    String param1 = String.valueOf(prefs.getInt("pmp", 1));
    String param2 = String.valueOf(prefs.getInt("ei", 1));

    URL = URL.replace("[x]", param1);
    URL = URL.replace("[y]", param2);

    //pegar id pmp e IE corretas
    JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request
            .Method.PUT, URL, jsonObject,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    callback.onSuccess(response + "");
                    success[0] = true;
                    progDailog.dismiss();
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {

                    callback.onFailure(error);
                    tokenFailure(error);
                    success[0] = false;
                    progDailog.dismiss();
                }
            }) {


        @Override
        public Map<String, String> getHeaders() throws
                AuthFailureError {

            HashMap<String, String> headers = new HashMap<>();
            headers.put("Token", token);

            return headers;
        }
    };

    int socketTimeout = 30000;
    RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);

    jsObjRequest.setRetryPolicy(policy);


    queue.add(jsObjRequest);

    return success[0];
}

My problem is that I send a very large JSON, so the default timeout of 5 seconds is not enough. So, I tried to increase the timeout to 30 seconds and messing with the DefaultRetryPolicy to increase the number of retries.

The thing is, it keeps timeouting in 5s and it doesn't even retry once!

Do I have to have a listener or a callback for the retries ? I'm doing something wrong with the DefaultRetryPolicy ? Please help, this issue is driving me nuts...

like image 379
Carlos Avatar asked Feb 19 '16 13:02

Carlos


2 Answers

Do you need to use the DefaultRetryPolicy?

Because you could define your own.

Instead of this:

RetryPolicy policy = new DefaultRetryPolicy(socketTimeout,     
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,     
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);

Try this:

jsObjRequest.setRetryPolicy(new RetryPolicy() {
    @Override
        public int getCurrentTimeout() { 
            // Here goes the new timeout
            return mySeconds; 
        }
        @Override
        public int getCurrentRetryCount() { 
            // The max number of attempts
            return myAttempts; 
        }
        @Override
        public void retry(VolleyError error) throws VolleyError {
            // Here you could check if the retry count has gotten
            // To the max number, and if so, send a VolleyError msg
            // or something    
        }
    });
like image 153
herrmartell Avatar answered Oct 03 '22 07:10

herrmartell


I'm not sure exactly why the retry time doesn't work on your code, I did find a similar issue here though.

Instead, I can tell you some things that I don't believe to be ok in your code and suggest you to adopt my model of Volley use.

First of all, you're creating a new request queue for every request you're making. That's not cool, you should have a RequestManager singleton that holds one request queue and use that.

Second of all, I don't know if this is what affects the retry time, I have a base request class and set the retry time in the constructor. Then, I extend this class whenever I have to implement a new type of request. Then, I create an instance of the request, set the callbacks, and pass it to the request manager. The request manager adds it to the one request queue I was talking about.

More over, if you don't already, I suggest you use the Gson library to parse the JSON objects.

This is my base request class I'm using:

/**
* Created by Daniel on 2/6/2016.
*/
public class GsonRequest<T> extends Request<T> {

protected Context context;
protected final Gson gson = new Gson();
protected final Class<T> clazz;
protected final TypeToken typeToken;
protected Map<String, String> headers;
protected Map<String, String> params;
protected final Response.Listener<T> listener;

/**
 * Make a GET request and return a parsed object from JSON.
 *
 * @param url   URL of the request to make
 * @param clazz Relevant class object, for Gson's reflection
 */
public GsonRequest(final Context context, final int requestMethod, String url, Class<T> clazz, Response.Listener<T> listener, Response.ErrorListener errorListener) {
    super(requestMethod, url, errorListener);
    this.context = context;
    this.clazz = clazz;
    this.listener = listener;
    this.headers = new HashMap<>();
    typeToken = null;
    setRetryPolicy();
}

/**
 * Make a GET request and return a parsed object from JSON.
 *
 * @param url       URL of the request to make
 * @param typeToken Relevant typeToken object, for Gson's reflection
 */
public GsonRequest(final Context context, final int requestMethod, String url, TypeToken typeToken, Response.Listener<T> listener, Response.ErrorListener errorListener) {
    super(requestMethod, url, errorListener);
    this.context = context;
    this.typeToken = typeToken;
    this.listener = listener;
    this.headers = new HashMap<>();
    clazz = null;
    setRetryPolicy();
}

@Override
protected Map<String, String> getParams() throws AuthFailureError {
    return params != null ? params : super.getParams();
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    //TODO add headers here
    return headers;
}

@Override
protected void deliverResponse(T response) {
    listener.onResponse(response);
}

@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
    try {
        String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        JSONObject jsonObject = new JSONObject(json);
        if (clazz != null) {
            return Response.success(gson.fromJson(json, clazz), HttpHeaderParser.parseCacheHeaders(response));
        } else {
            return Response.success((T) gson.fromJson(json, typeToken.getType()), HttpHeaderParser.parseCacheHeaders(response));
        }
    } catch (UnsupportedEncodingException e) {
        return Response.error(new ParseError(e));
    } catch (JsonSyntaxException e) {
        return Response.error(new ParseError(e));
    } catch (JSONException e) {
        return Response.error(new ParseError(e));
    }
}

protected void setRetryPolicy() {
    //TODO set your retry policy here
    setRetryPolicy(new DefaultRetryPolicy(
            30000,
            DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
}
}`enter code here`

This works like a charm for me. Hope it helps, if you need any further help, contact me

like image 26
DDsix Avatar answered Oct 03 '22 07:10

DDsix