Android Volley library: do we always have to repeat Response.Listener and Response.ErrorListener
Asked Answered
T

2

7

I have recently started using Android Volley in my project. The common practice mentioned in most of the tutorials is to use it this way:

JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET,
            url, null,
            new Response.Listener<JSONObject>() {

                @Override
                public void onResponse(JSONObject response) {
                    // do something
                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                    // do something.
                }
            });

My query is - Do we have to repeat this code every where wherever we need to make a request. I was trying to put in a common onResponse and onErrorResponse handler by creating a helper class :

public class CustomJSONObjectRequest extends JsonObjectRequest {
    private BaseResource resource;
    private String queryId;
    private String paramArgs;

    public CustomJSONObjectRequest(int method, String url, JSONObject 
                               jsonRequest, 
                               Response.Listener<JSONObject> listener,
                               final Response.ErrorListener errorListener, 
                               final Context ctx,
                               final BaseResource baseResource) {
    super(method, url, jsonRequest,
            new Response.Listener<JSONObject>() {
                 // some common code for all BaseResources
            },
            new Response.ErrorListener() {
                // some common code
            });
}

But the problem with this approach is that I need to pass in each and every thing in the constructor itself, which is making me feel like I am not doing it correctly. For example, if i need to pass some query parameters for the url, i need to always pass in the complete url from the caller although I can still have a common logic to generate the url in one place.

Can someone please let me know what is the best way of achieving something like this.

Teacake answered 19/9, 2015 at 20:35 Comment(0)
K
15

You can refer to my sample code as the following:

public interface VolleyResponseListener {
    void onError(String message);

    void onResponse(Object response);
}

Then in my VolleyUtils class:

public static void makeJsonObjectRequest(Context context, String url, final VolleyResponseListener listener) {
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
                (url, null, new Response.Listener<JSONObject>() {

                @Override
                public void onResponse(JSONObject response) {
                    listener.onResponse(response);
                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                    listener.onError(error.toString());
                }
            }) {

        @Override
        protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
            try {
                String jsonString = new String(response.data,
                        HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET));
                return Response.success(new JSONObject(jsonString),
                        HttpHeaderParser.parseCacheHeaders(response));
            } catch (UnsupportedEncodingException e) {
                return Response.error(new ParseError(e));
            } catch (JSONException je) {
                return Response.error(new ParseError(je));
            }
        }
    };

    // Access the RequestQueue through singleton class.
    VolleySingleton.getInstance(context).addToRequestQueue(jsonObjectRequest);
}

Then in Activity:

VolleyUtils.makeJsonObjectRequest(mContext, url, new VolleyResponseListener() {
        @Override
        public void onError(String message) {

        }

        @Override
        public void onResponse(Object response) {

        }
    });

Another way is creating a VolleyResponseListener variable then passing it into methods of VolleyUtils class, as my answer in the following question:

Android: How to return async JSONObject from method using Volley?

Hope this helps!

Keeling answered 19/9, 2015 at 23:4 Comment(17)
Thanks for the response ! Another lame query - can i put common functionality in the interface methods ? So that i only override them whenever needed.Teacake
@Teacake for optional methods, IMO, you should read this questionKeeling
I think there is a misunderstanding. My question is regarding keeping a common onResponse() routine, so that i need not provide onResponse() in all the activities. Even with interface, i need to always provide a custom response handler in the activities. Is it okay to even think in that direction ?Teacake
I have not tried such thing yet but how do you think the activities' UI will be updated? You will have to pass all the essential views into the helper class methods?Keeling
I actually just wanted to provide a default onResponse() method which would just fetch the resources from server and return me the data. But yeah, you are right, do be able to get the UI thread react to it, i need to pass these handler from the Activity itself.Teacake
Another small thing.. do you create separate calls / classes for handling POST and GET or simply pass the Request type and override getParams() ? In any case I am accepting your answer as I am going to use interface from now onwards.Teacake
Can you clarify that or give examples? Sorry because I am online on mobile, so I cannot post more codes at the presentKeeling
Moreover, I haven't ever used getParams, but getBody :-)Keeling
I am using getParams to set the query parameters for GET requests. I will also check about getBody. Do you know of any good open source usage of Volley ( i know I am asking a lot today :) )Teacake
From developer.android.com/training/volley/index.html, git clone the full official source code of Google :-)Keeling
Input parameters Where have you written? Please complete your code.Cookgeneral
@ImanMarashi it depends on the inside JsonObjectRequest, you can read its contructors (by pressing Ctrl-B at JsonObjectRequest) and modify as your requirementKeeling
@Keeling Just one query, let's say my base activity/fragment implements the VolleyResponseListener, and there are child activities/fragment which have multiple API calls. Is it good practice to check the type of response, like (object instanceof JSONObject)?Mirisola
@Keeling Sorry, to bother you, but, there is a use-case,of which I am not getting clarity. Let's say, there is one screen say it dashboard, which have 5 web service calls. In that case how the response listener should be implemented? Or should we have five methods for fetching data?Mirisola
@Mirisola as you see at the end of my answer, VolleyUtils.makeJsonObjectRequest... each request will have its own listener. If you want to use the same listener for all requests (as in #32375795), you should identify that response is for which request, right?Keeling
@Keeling Yes, that is the main concern. Some mechanism have to be implemented for identifying the request.Mirisola
@Mirisola I see. A temporary solution is sending an ID/key in the request, and the response also has that ID inside, perhaps this is not a good solution :)Keeling
V
0

Create a class (like "ApiManager") that you pass the url and parameters, that creates the Volley request and keeps track of the replies and listeners. The ApiManager would typically get a callback from the calling class for the results. This way, you have to type the Volley code only once, while the logic for each call would be concise. Or, that's how I do it.

Vesperal answered 19/9, 2015 at 20:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.