¿Puedo hacer una solicitud sincrónica con volea?
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.
Parece que es posible con RequestFuture
la 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
}
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;
}