Hola, tenemos la solución a tu interrogante, continúa leyendo y la obtendrás a continuación.
Solución:
Parece que es posible con Volley’s RequestFuture
clase. Por ejemplo, para crear una solicitud JSON HTTP GET síncrona, puede hacer lo siguiente:
RequestFuture 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
Tenga en cuenta que la respuesta de @Matthews es correcta, PERO si está en otro hilo y hace una llamada de descarga cuando no tiene Internet, su devolución de llamada de error se llamará en el hilo principal, pero el hilo en el que se encuentra se bloqueará PARA SIEMPRE. (Por lo tanto, si ese hilo es un IntentService, nunca podrá enviarle otro mensaje y su servicio estará básicamente inactivo).
Usa la versión de get()
que tiene un tiempo de espera future.get(30, TimeUnit.SECONDS)
y detecta el error para salir de tu hilo.
Para que coincida con la respuesta de @Mathews:
try
return future.get(30, TimeUnit.SECONDS);
catch (InterruptedException e)
// exception handling
catch (ExecutionException e)
// exception handling
catch (TimeoutException e)
// exception handling
A continuación, lo envolví en un método y uso una solicitud diferente:
/**
* 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 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;
Probablemente se recomiende usar Futures, pero si por alguna razón no quiere, en lugar de cocinar su propio bloqueo sincronizado, debe usar un java.util.concurrent.CountDownLatch
. Entonces eso funcionaría así …
//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()
@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...
Dado que la gente parecía intentar hacer esto y se encontró con algunos problemas, decidí que en realidad proporcionaría una muestra de trabajo de la “vida real” de esto en uso. Aquí está https://github.com/timolehto/SynchronousVolleySample
Ahora, aunque la solución funciona, tiene algunas limitaciones. Lo más importante es que no puede llamarlo en el subproceso principal de la interfaz de usuario. Volley ejecuta las solicitudes en segundo plano, pero por defecto Volley usa el principal Looper
de la aplicación para enviar las respuestas. Esto provoca un interbloqueo ya que el subproceso principal de la interfaz de usuario está esperando la respuesta, pero el Looper
Esta esperando por onCreate
para terminar antes de procesar la entrega. Si realmente quieres hacer esto, podrías, en lugar del static métodos auxiliares, crea una instancia propia RequestQueue
pasándolo por tu cuenta ExecutorDelivery
atado a un Handler
usando un Looper
que está vinculado a un hilo diferente del hilo principal de la interfaz de usuario.
Sección de Reseñas y Valoraciones
Si posees algún titubeo o forma de aumentar nuestro post puedes realizar una aclaración y con mucho gusto lo observaremos.