Volley – solicitud de http en bloqueo
Estoy aprendiendo a usar Google Volley en estos días. Es muy conveniente para una conexión rápida. Parece que todas las solicitudes se están ejecutando en el fondo en Volley. Por ejemplo:
volleyRequestQueue.add(new JsonObjectRequest(Method.POST, SIGNUP_URL, reqBody, new SignUpResponseListener(), new MyErrorListener()));
Utilizando el código anterior, podemos realizar una llamada POST que se ejecuta en segundo plano (modo no bloqueante). Ahora mi pregunta es: ¿Es posible hacer la llamada POST de la manera de bloqueo? ¿Por qué necesito una forma de bloqueo para hacer una llamada REST? Debido a que algunas llamadas, como iniciar sesión, deben hacerse antes de hacer otra cosa.
- Respuesta HTML desde el servidor
- Publicar en Ruby on Rails la aplicación de android
- Retrofit que lanza IllegalArgumentException exception for asynchronous FormUrlEncoded DELETE call
- ¿Cómo publico datos usando la biblioteca okhttp con el tipo de contenido x-www-form-urlencoded?
- ¿Cómo calcular el precio en la cantidad de datos JSON y Post datos?
Gracias
- Uso de Jsoup en los datos de inicio de sesión de POST
- Enviar solicitud de publicación con params utilizando Retrofit
- Android: Obtener respuesta de una URL https
- Enviar datos a la página cargada en WebView
- Cambiar la solicitud de publicación HTTP a HTTPS:
- Cómo enviar datos POST con código en una vista web de Android
- Solicitud de publicación de Android WebView con encabezados personalizados
- Android HttpUrlConnection hace POST en lugar de GET
Volley admite la solicitud de bloqueo a través de RequestFutures. Crear una solicitud normal, pero establecer sus devoluciones de llamada como su futuro solicitud, que es sólo la extensión de volley de un estándar java futuros. La llamada a future.get () bloqueará.
Parece algo como esto
RequestFuture<JSONObject> future = RequestFuture.newFuture(); JsonObjectRequest request = new JsonObjectRequest(Method.POST, SIGNUP_URL, reqBody, future, future) volleyRequestQueue.add(request); try { JSONObject response = future.get(); } catch (InterruptedException e) { } catch (ExecutionException e) { }
Aquí está una respuesta más clara que maneja InterruptedException
correctamente así como tiempo de espera. Tenga en cuenta que la única vez que desearía tragar la interrupción y continuar es si específicamente desea utilizar la interrupción para cancelar la respuesta a la solicitud.
RequestFuture<JSONObject> future = RequestFuture.newFuture(); JsonObjectRequest request = new JsonObjectRequest(Method.POST, SIGNUP_URL, reqBody, future, future); volleyRequestQueue.add(request); try { JSONObject response = null; while (response == null) { try { response = future.get(30, TimeUnit.SECONDS); // Block thread, waiting for response, timeout after 30 seconds } catch (InterruptedException e) { // Received interrupt signal, but still don't have response // Restore thread's interrupted status to use higher up on the call stack Thread.currentThread().interrupt(); // Continue waiting for response (unless you specifically intend to use the interrupt to cancel your request) } } // Do something with response, ie new SignUpResponseListener().onResponse(response); } catch (ExecutionException e) { // Do something with error, ie new MyErrorListener().onErrorResponse(new VolleyError(e)); } catch (TimeoutException e) { // Do something with timeout, ie new MyErrorListener().onErrorResponse(new VolleyError(e)); }
Si desea hacer algo exactamente después de la solicitud Volley, utilice un listener callback onSuccess (SignUpResponseListener en ese caso) y coloque el código allí. Esta es la mejor práctica.
Quiero añadir algo a la respuesta de Gabriel. Mientras que RequestFuture
bloquea el subproceso del que se llama y sirve a su propósito, la solicitud de red en sí no se lleva a cabo en ese hilo. En su lugar, se lleva a cabo en un hilo de fondo.
Por lo que entiendo después de pasar por la biblioteca, las solicitudes en el RequestQueue
se despachan en su método start()
:
public void start() { .... mCacheDispatcher = new CacheDispatcher(...); mCacheDispatcher.start(); .... NetworkDispatcher networkDispatcher = new NetworkDispatcher(...); networkDispatcher.start(); .... }
Ahora las clases de CacheDispatcher
y NetworkDispatcher
extienden el hilo. Tan eficazmente se genera un nuevo subproceso de trabajo para deshacer la cola de solicitudes y la respuesta se devuelve a los oyentes de éxito y error implementados internamente por RequestFuture
.
Así que no veo ningún punto en hacer un hilo de bloqueo separado para usar RequestFuture
. En lugar de lo que Makibo mencionó en su respuesta – "utilizar un oyente de llamada de retorno onSuccess (SignUpResponseListener en ese caso) y poner el código allí."
No podría conseguir el trabajo de RequestFuture así que apenas utilicé un oyente de la llamada de vuelta como Makibo sugirió. No tengo ni idea de por qué fue downvoted, esta es probablemente la mejor solución para el problema común original de diferentes solicitudes Volley que todo depende de un inicio de sesión o algo. En este ejemplo, quiero subir una foto, pero primero tengo que comprobar si el usuario está conectado o no. Si no, tengo que iniciar sesión y luego esperar el éxito antes de subir la foto. Si ya has iniciado sesión, sólo tienes que ir directamente a subir la foto.
Aquí está mi código de ejemplo:
// interface we'll use for listener public interface OnLoginListener { public void onLogin(); } public void uploadPhoto(final String username, final String password, final String photo_location) { // first setup callback listener that will be called if/when user is logged in OnLoginListener onLoginListener=new OnLoginListener() { @Override public void onLogin() { uploadPhotoLoggedIn(photo_location); } }; // simplistic already logged in check for this example, just checking if username is null if (loggedInUsername==null) { // if it null, login and pass listener httpLogin(username, password, onLoginListener); } else { // if not null, already logged in so just call listener method onLoginListener.onLogin(); } } public void httpLogin(String username, String password, final OnLoginListener onLoginListener) { StringRequest loginRequest = new StringRequest(Request.Method.POST, "https://www.example.com/login.php", new Response.Listener<String>() { @Override public void onResponse(String txtResponse) { Log.d("STACKOVERFLOW",txtResponse); // call method of listener after login is successful. so uploadPhotoLoggedIn will be called now onLoginListener.onLogin(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // TODO Auto-generated method stub Log.d("VOLLEYERROR","error => "+error.toString()); } } ) { }; // Just getting the Volley request queue from my application class (GetApplicatio.java), and adding request GetApplication.getRequestQueue().add(loginRequest); }
- En android hay alguna manera de preservar SharedPreferences después de una desinstalación
- Abrir o ver el contenido de un archivo .txt con adb shell android