Android - Wait for volley response to return
Asked Answered
J

4

25

I need execute a Volley request and wait for the response to parse it and return it, but have no idea on how to achieve this. Can someone help?

What I have now is this:

public String getLink() {
    JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

            @Override
            public void onResponse(JSONObject response) {
                shortenURL = response.getString("url");
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                // TODO Auto-generated method stub

           }
    });

    queue.add(jsObjRequest);

    return shortenURL;
}
Jaimiejain answered 23/5, 2014 at 16:14 Comment(0)
C
34

A reusable Factory method design pattern solution:

To return or get Volley response from another method, you need to write a Callback functionality, which is all easy using Interfaces

This simple solution is taken from my MVC architecture for Android apps developed with complete reusability and separation of concern concept.

Supposing JSONObject is your response from server

Step 1)

Create an Interface ServerCallback

package xx.xx.xx.utils;

    import org.json.JSONObject;

    public interface ServerCallback{
        void onSuccess(JSONObject result);
    }

Step 2) Supposing yours Volley server request method is in Controller or any other shared 'context' class do this in yours any Activity

Controller controller = new Controller();
controller.youFunctionForVolleyRequest(email, password, this, loginUrl, new ServerCallback() {
                    @Override
                    public void onSuccess(JSONObject response) {
                       // do stuff here 
                    }
                  }
               );

3) In your Controller class, call ServerCallback function in inResponse() which will execute yours code in Activity only on the response from the server- mission accomplished!

 public void youFunctionForVolleyRequest(final String email , final String password ,final Context context , final String URL, final ServerCallback callback)
    {
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("email", email);
        params.put("password", password);

        Log.e("sending json",params.toString());
        JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
                URL, new JSONObject(params), new Response.Listener<JSONObject>()
        {

            @Override
            public void onResponse(JSONObject response) {
               callback.onSuccess(response); // call call back function here

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                //VolleyLog.d("Volley error json object ", "Error: " + error.getMessage());

            }
        }){
            @Override
            public String getBodyContentType()
            {
                return "application/json";
            }
        };

        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(jsonObjReq);

    }
Cartel answered 19/1, 2016 at 13:40 Comment(2)
what about controller object. is they are automatically destroyed? or There is chance for garbage collection if so much objects are created during flow of appHyacinthe
@rajesh If i am right your implementation only have very less network calls. For apps like ecommerce in a single page you will have 5-10. Different sources of network calls. Not following a factory pattern can lead to huge code redunadnacy across multiple activities. The gc will accur for non static objects of Controller classCartel
3
15

You should probably not return the link in your method.

Volley is doing asynchronous tasks, it means that you can't know when the answer will arrive from your webservice, it could be 10sec or 10min.

If you need the string in your function you should probably create a method and call it when you have the result.

Here is an example:

I guess this is what you have

public void getTheLinkAndCallDoSomething(){
    String link = getLink();
    doSomethingWithTheLink(link);
}

This would work if getLink() answers in a synchronous way. Volley is not in this case.

And this is what you can do with Volley:

public void getTheLinkAndCallDoSomething(){
     JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, 
                               url, null, new Response.Listener<JSONObject>() {

                    @Override
                    public void onResponse(JSONObject response) {
                        shortenURL = response.getString("url");
                        doSomethingWithTheLink(shortenURL);
                    }
                }, new Response.ErrorListener() {

                    @Override
                    public void onErrorResponse(VolleyError error) {
                        // TODO Auto-generated method stub

                    }
                });

    queue.add(jsObjRequest);
}

In this case, you call the WS to get your url. And as soon as the result is known, you call doSomethingWithTheLink()

Whatever, if you really do want to be synchronous you can look at this post : Wait for result of Async Volley request and return it

Also, be aware that waiting for an answer could freeze your app UI and I guess that is not what you want.

3d answered 23/5, 2014 at 17:22 Comment(1)
Invert logic thing. Thanks a lot :DKus
P
1

you cannot return anydata in your getLink() method. Use your code as

String shortenURL  = ""; // activity global variable



public void getLink() {
        JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

                    @Override
                    public void onResponse(JSONObject response) {
                        shortenURL = response.getString("url");
                    }
                }, new Response.ErrorListener() {

                    @Override
                    public void onErrorResponse(VolleyError error) {
                        // TODO Auto-generated method stub

                    }
                });

                queue.add(jsObjRequest);

}

You can also see more info at http://arnab.ch/blog/2013/08/asynchronous-http-requests-in-android-using-volley/

Pendent answered 23/5, 2014 at 17:25 Comment(0)
M
0

You can do this using the future concept

 RequestFuture<JSONObject> jsonObjectRequestFuture = RequestFuture.newFuture();
    JsonObjectRequest request = new JsonObjectRequest(ServiceUrl.BFF_BASE_URL + path, (JSONObject) postBody, jsonObjectRequestFuture, jsonObjectRequestFuture);
requestQueue.add(request);
JSONObject jsonObject = jsonObjectRequestFuture.get(30, TimeUnit.SECONDS);
Malinowski answered 27/8, 2019 at 7:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.