Can I do a synchronous request with volley? Can I do a synchronous request with volley? android android

Can I do a synchronous request with volley?


It looks like it is possible with Volley's RequestFuture class. For example, to create a synchronous JSON HTTP GET request, you can do the following:

RequestFuture<JSONObject> future = RequestFuture.newFuture();JsonObjectRequest request = new JsonObjectRequest(URL, new JSONObject(), future, future);requestQueue.add(request);try {  JSONObject response = future.get(); // this will block} catch (InterruptedException e) {  // exception handling} catch (ExecutionException e) {  // exception handling}


Note @Matthews answer is correct BUT if you are on another thread and you do a volley call when you have no internet, your error callback will be called on the main thread, but the thread you are on will be blocked FOREVER. (Therefore if that thread is an IntentService, you will never be able to send another message to it and your service will be basically dead).

Use the version of get() that has a timeout future.get(30, TimeUnit.SECONDS) and catch the error to exit your thread.

To match @Mathews answer:

        try {            return future.get(30, TimeUnit.SECONDS);        } catch (InterruptedException e) {            // exception handling        } catch (ExecutionException e) {            // exception handling        } catch (TimeoutException e) {            // exception handling        }

Below I wrapped it in a method & use a different request:

   /**     * Runs a blocking Volley request     *     * @param method        get/put/post etc     * @param url           endpoint     * @param errorListener handles errors     * @return the input stream result or exception: NOTE returns null once the onErrorResponse listener has been called     */    public InputStream runInputStreamRequest(int method, String url, Response.ErrorListener errorListener) {        RequestFuture<InputStream> future = RequestFuture.newFuture();        InputStreamRequest request = new InputStreamRequest(method, url, future, errorListener);        getQueue().add(request);        try {            return future.get(REQUEST_TIMEOUT, TimeUnit.SECONDS);        } catch (InterruptedException e) {            Log.e("Retrieve cards api call interrupted.", e);            errorListener.onErrorResponse(new VolleyError(e));        } catch (ExecutionException e) {            Log.e("Retrieve cards api call failed.", e);            errorListener.onErrorResponse(new VolleyError(e));        } catch (TimeoutException e) {            Log.e("Retrieve cards api call timed out.", e);            errorListener.onErrorResponse(new VolleyError(e));        }        return null;    }


It is probably recommended to use the Futures, but if for whatever reason you don't want to, instead of cooking your own synchronized blocking thing you should use a java.util.concurrent.CountDownLatch. So that would work like this..

//I'm running this in an instrumentation test, in real life you'd ofc obtain the context differently...final Context context = InstrumentationRegistry.getTargetContext();final RequestQueue queue = Volley.newRequestQueue(context);final CountDownLatch countDownLatch = new CountDownLatch(1);final Object[] responseHolder = new Object[1];final StringRequest stringRequest = new StringRequest(Request.Method.GET, "http://google.com", new Response.Listener<String>() {    @Override    public void onResponse(String response) {        responseHolder[0] = response;        countDownLatch.countDown();    }}, new Response.ErrorListener() {    @Override    public void onErrorResponse(VolleyError error) {        responseHolder[0] = error;        countDownLatch.countDown();    }});queue.add(stringRequest);try {    countDownLatch.await();} catch (InterruptedException e) {    throw new RuntimeException(e);}if (responseHolder[0] instanceof VolleyError) {    final VolleyError volleyError = (VolleyError) responseHolder[0];    //TODO: Handle error...} else {    final String response = (String) responseHolder[0];    //TODO: Handle response...}

Since people seemed to actually try to do this and ran into some trouble I decided I'd actually provide a "real life" working sample of this in use. Here it is https://github.com/timolehto/SynchronousVolleySample

Now even though the solution works, it has some limitations. Most importantly, you can't call it on the main UI thread. Volley does execute the requests on the background, but by default Volley uses the main Looper of the application to dispatch the responses. This causes a deadlock as the main UI thread is waiting for the response, but the Looper is waiting for onCreate to finish before processing the delivery. If you really really want to do this you could, instead of the static helper methods, instantiate your own RequestQueue passing it your own ExecutorDelivery tied to a Handler using a Looper which is tied to different thread from the main UI thread.