¿Puedo hacer una solicitud sincrónica con volea?

Resuelto LocoMike asked hace 54 años • 8 respuestas

Imagina que estoy en un Servicio que ya tiene un hilo en segundo plano. ¿Puedo hacer una solicitud usando volley en ese mismo hilo, para que las devoluciones de llamada se realicen sincrónicamente?

Hay 2 razones para esto:

  • Primero, no necesito otro hilo y sería un desperdicio crearlo.
  • En segundo lugar, si estoy en un ServiceIntent, la ejecución del hilo finalizará antes de la devolución de llamada y, por lo tanto, no recibiré respuesta de Volley. Sé que puedo crear mi propio Servicio que tenga algún subproceso con un bucle de ejecución que pueda controlar, pero sería deseable tener esta funcionalidad en volley.
LocoMike avatar Jan 01 '70 08:01 LocoMike
Aceptado

Parece que es posible con RequestFuturela clase de Volley. Por ejemplo, para crear una solicitud JSON HTTP GET sincrónica, puede hacer lo siguiente:

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
}
Matthew avatar Jun 11 '2013 01:06 Matthew

Tenga en cuenta que la respuesta de @Matthews es correcta, PERO si está en otro hilo y realiza una llamada de volea 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 muerto).

Utilice la versión get()que tiene un tiempo de espera future.get(30, TimeUnit.SECONDS)y detecte el error para salir del hilo.

Para coincidir 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 utilicé 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<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;
    }
Blundell avatar May 22 '2014 13:05 Blundell