Saltar al contenido

¿Puedo hacer una solicitud síncrona con volley?

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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *