Android / Java: cómo retrasar el retorno en un método

Quiero crear una clase de Utils para simplificar las llamadas de Volley, como esta:

Utils.java:

public class Utils { static JsonObjectRequest mJsonObjectRequest; protected static boolean busy = true; public static JSONObject makeJsonObjectRequest(Context context, int method, String url){ final JSONObject[] jsonObject = new JSONObject[1]; mJsonObjectRequest = new JsonObjectRequest (method, url, null, new Response.Listener() { @Override public void onResponse(JSONObject response) { jsonObject[0] = response; busy = false; } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // TODO Auto-generated method stub try { jsonObject[0] = new JSONObject(error.toString()); } catch (JSONException e) { e.printStackTrace(); } busy = false; } }); // Access the RequestQueue through your singleton class. VolleySingleton.getInstance(context).addToRequestQueue(mJsonObjectRequest); while (true) { if (!busy) break; } return jsonObject[0]; } } 

MainActivity.java:

 JSONObject jsonObject = Utils.makeJsonObjectRequest(this, Request.Method.GET, url); mTxtDisplay.setText("Response: " + jsonObject.toString()); 

Cuando se ejecuta la aplicación, jsonObject siempre es nulo. Quiero preguntar si puedo retrasar el retorno de jsonObject [0] dentro de makeJsonObjectRequest hasta que se llame onResponse. ¿Puedo hacer eso y cómo? .

Creé esto y lo gestioné de la siguiente manera, por favor eche un vistazo, espero que sea útil para usted

 public class APIManager { public static void createRequest(Context c, String requestTag, String endPoint, List params, final OnRequestCompletedListener listener, TransParentProgressDialog pd) { ServerDetails serverDetails = new ServerDetails(c, endPoint, params); JsonObjectRequest request = new JsonObjectRequest(Method.GET, serverDetails.getQueryUrl(), null, new Response.Listener() { @Override public void onResponse(JSONObject response) { listener.onRequestCompleted(response); } }, getErrorListener(c, pd)) { }; AppController.getInstance().addToRequestQueue(request, requestTag); } public static ErrorListener getErrorListener(final Context c, final TransParentProgressDialog pd, final TextView tvEmpty, final String errorText) { Response.ErrorListener listener = new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { if (pd != null && pd.isShowing()) { pd.dismiss(); } if (tvEmpty != null) { tvEmpty.setText(errorText); } MyDialog dialog; Log.d("volley-error", error.toString()); if (error instanceof TimeoutError) { dialog = new MyDialog(c, "Server Timeout"); dialog.show(); return; } else if (error instanceof NoConnectionError) { dialog = new MyDialog(c, "No Connection or Invalid Url"); dialog.show(); return; } else if (error instanceof ServerError) { NetworkResponse response = error.networkResponse; if (response != null) { // int statusCode = response.statusCode; byte[] data = response.data; if (data != null) { String str = new String(data); try { JSONObject object = new JSONObject(str); Log.d("error response", object.toString()); if (object.has("errors")) { JSONArray errors = object .getJSONArray("errors"); JSONObject errorObject = errors .getJSONObject(0); dialog = new MyDialog(c, "Error!", errorObject.getString("message")); dialog.show(); } else { dialog = new MyDialog(c, "Error!", object.toString()); dialog.show(); } } catch (JSONException e) { e.printStackTrace(); dialog = new MyDialog(c, "Error!", "Error"); dialog.show(); } } else { dialog = new MyDialog(c, "Server Error"); dialog.show(); } } else { dialog = new MyDialog(c, "Server Error"); dialog.show(); } } else if (error instanceof NetworkError) { NetworkResponse response = error.networkResponse; if (response != null) { // int statusCode = response.statusCode; byte[] data = response.data; if (data != null) { String str = new String(data); try { JSONObject object = new JSONObject(str); Log.d("error response", object.toString()); if (object.has("errors")) { JSONArray errors = object .getJSONArray("errors"); JSONObject errorObject = errors .getJSONObject(0); dialog = new MyDialog(c, "Error!", errorObject.getString("message")); dialog.show(); } else { dialog = new MyDialog(c, "Error!", object.toString()); dialog.show(); } } catch (JSONException e) { e.printStackTrace(); dialog = new MyDialog(c, "Error!", "Error"); dialog.show(); } } else { dialog = new MyDialog(c, "Network Error"); dialog.show(); } } else { dialog = new MyDialog(c, "Network Error"); dialog.show(); } } else if (error instanceof ParseError) { dialog = new MyDialog(c, "Parse Error"); dialog.show(); } else if (error instanceof AuthFailureError) { NetworkResponse response = error.networkResponse; if (response != null) { // int statusCode = response.statusCode; byte[] data = response.data; if (data != null) { String str = new String(data); try { JSONObject object = new JSONObject(str); Log.d("error response", object.toString()); if (object.has("errors")) { JSONArray errors = object .getJSONArray("errors"); JSONObject errorObject = errors .getJSONObject(0); dialog = new MyDialog(c, "Error!", errorObject.getString("message")); dialog.show(); } else { dialog = new MyDialog(c, "Error!", object.toString()); dialog.show(); } } catch (JSONException e) { e.printStackTrace(); dialog = new MyDialog(c, "Error!", "Error"); dialog.show(); } } else { dialog = new MyDialog(c, "Error!", "Error"); dialog.show(); } } else { dialog = new MyDialog(c, "Error connecting server"); dialog.show(); } } } }; return listener; } } 

Y la interfaz para devolver la llamada a solicitud completa es

 public interface OnRequestCompletedListener { public void onRequestCompleted(JSONObject response); } 

Si ejecuta makeJsonObjectRequest en una makeJsonObjectRequest de fondo, puede ejecutar la solicitud de Volley síncrono de esta manera: ¿Puedo hacer una solicitud sincrónica con volley?

Si ejecuta makeJsonObjectRequest en el hilo de UI, entonces no debería esperar a onResponse para evitar el locking del subproceso de UI. Use la callback en este caso.

Gracias a las respuestas de @Gennadii Saprykin y @Gopal Singh Sirvi, he intentado tanto las formas de llamada ineludible como de interfaz. Ambos funcionaron, sin embargo, prefiero el modo Escuchador.

OnRequestCompletedListener.java:

 package com.example.volleyapp; import org.json.JSONObject; public interface OnRequestCompletedListener { void onRequestCompleted(JSONObject response); } 

Utils.java:

 package com.example.volleyapp; import android.content.Context; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.JsonObjectRequest; import org.json.JSONException; import org.json.JSONObject; import java.util.concurrent.Callable; public class Utils { static JsonObjectRequest mJsonObjectRequest; static Callable func=null; public static void makeJsonObjectRequest_Listener(final Context context, final int method, final String url, final OnRequestCompletedListener listener){ mJsonObjectRequest = new JsonObjectRequest (method, url, null, new Response.Listener() { @Override public void onResponse(JSONObject response) { listener.onRequestCompleted(response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // TODO Auto-generated method stub try { listener.onRequestCompleted(new JSONObject(error.toString())); } catch (JSONException e) { e.printStackTrace(); } } }); // Access the RequestQueue through your singleton class. VolleySingleton.getInstance(context).addToRequestQueue(mJsonObjectRequest); } public static void makeJsonObjectRequest_Callable(final Context context, final int method, final String url, final MainActivity.JsonCallable doRequest){ mJsonObjectRequest = new JsonObjectRequest (method, url, null, new Response.Listener() { @Override public void onResponse(JSONObject response) { try{ func = doRequest; doRequest.jsonObject = response; func.call(); } catch (Exception e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // TODO Auto-generated method stub try { func = doRequest; doRequest.jsonObject = new JSONObject(error.toString()); func.call(); } catch (JSONException e) { e.printStackTrace(); } } }); // Access the RequestQueue through your singleton class. VolleySingleton.getInstance(context).addToRequestQueue(mJsonObjectRequest); } } 

MainActivity.java:

 package com.example.volleyapp; import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import org.json.JSONObject; import java.util.concurrent.Callable; public class MainActivity extends Activity { JsonCallable jsonCallable=null; TextView mTxtDisplay; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTxtDisplay = (TextView) findViewById(R.id.textView); String url = "https://10.0.2.2/aspnet/webapi/products/1"; // Callable way // jsonCallable = new JsonCallable(); // Utils.makeJsonObjectRequest_Callable(this, Request.Method.GET, url, jsonCallable); // Listener way OnRequestCompletedListener listener = new OnRequestCompletedListener() { @Override public void onRequestCompleted(JSONObject response) { mTxtDisplay.setText(response.toString()); } }; Utils.makeJsonObjectRequest_Listener(this, Request.Method.GET, url, listener); } class JsonCallable implements Callable { public JSONObject jsonObject; public JsonCallable(){ } @Override public Object call() throws Exception { mTxtDisplay.setText(jsonObject.toString()); return null; } } } 

Una vez más, ¡gracias a todos por su ayuda!