Android/Java: how to delay return in a method

2020-01-27 08:23发布

I want to build a Utils class to make Volley calls simpler, like this:

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<JSONObject>() {

                @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());

When app runs, jsonObject always null. I want to ask if I can delay return jsonObject[0] inside makeJsonObjectRequest until onResponse called. Can I do that and how? .

3条回答
Anthone
2楼-- · 2020-01-27 08:24

I created this and managed like the following way please have a look, hope it will be useful to you

public class APIManager {



    public static void createRequest(Context c, String requestTag,
            String endPoint, List<NameValuePair> 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<JSONObject>() {

                    @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;
    }
}

And the interface for call back on request completed is

public interface OnRequestCompletedListener {

        public void onRequestCompleted(JSONObject response);
    }
查看更多
一纸荒年 Trace。
3楼-- · 2020-01-27 08:33

Thanks to @Gennadii Saprykin's and @Gopal Singh Sirvi's answers, I have tried both Callable and Interface Listener ways. Both worked, however, I prefer Listener way.

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<Void> 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<JSONObject>() {

                    @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<JSONObject>() {

                    @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;
        }
    }
}

Once again, thank you all for your help!

查看更多
▲ chillily
4楼-- · 2020-01-27 08:49

If you execute makeJsonObjectRequest on a background thread, then you can execute synchronous Volley request this way: Can I do a synchronous request with volley?

If you execute makeJsonObjectRequest on the UI thread, then you shouldn't wait for onResponse to avoid blocking UI thread. Use callback in this case.

查看更多
登录 后发表回答