Android Volley tutorial Android 18.07.2017

Volley is an HTTP library developed by Google to ease networking tasks in Android Applications. Volley can handle almost each and everything you will need to do over the network, it handles HTTP request and also manages the async tasks that you need to use while working with canonical networking classes.

Features of Android Volley library:

  • Volley manages network request automatically and without you using any AsyncTask. It offers multiple concurrent network connections, resulting in faster and efficient network operations.
  • Volley has a custom view called NetworkImageView (subclassing ImageView) that makes it easy to load images. You can set the URL along with a default ViewHolder.
  • Volley is a REST client that makes common networking tasks easy. It takes care of requesting, loading, caching, threading, and synchronization. You don’t have to worry about async tasks or thread handling.
  • Volley was designed for network operations that populate the UI. It is good for short operations, but not so good for large downloads, uploads, or streaming.
  • Volley chooses the internal HTTP transport layer based on the device. It chooses ApacheHttpClient on Froyo and HttpURLConnection on Gingerbread and above. This is no longer such a critical benefit because so few devices are running Froyo and the ApacheHttpClient is being discontinued.
  • Volley allows you to use external transports, such as OKHttp.
  • Volley has built-in JSON to parse responses.
  • Volley supports an extensive cancellation API, overcoming one of the pitfalls of implementing your own AsyncTasks.
  • Volley caches all network requests, utilizing the previous results in the case of change in activity configuration. However due to the same reason, it is only good for small Volley and not suitable for large download or streaming operations.

While using Volley you are only concerned about adding a request to the queue, handling it’s response, and you can actually ignore everything that is running in the background. When you fire a network request it is added to cache queue in the priority order. A cache dispatcher thread figures out whether it can service the request entirely from the cache or it needs to fire a network request for the response. In the case of a cache miss or if cached response has expired, the network dispatcher services the request, handles the parsing of the response and returns the response back to the main thread.

Volley is very useful for network request involving strings, images, and JSON. It has built in support for these objects.

  • JSON Object Request. Through class JsonObjectRequest.
  • JSON Array Request. Through class JsonArrayRequest.
  • String Request. Through class StringRequest.
  • Image Transfer Request. Through class ImageRequest.

To send a request, you simply construct one and add it to the RequestQueue with add(). Once you add the request it moves through the pipeline, gets serviced, and has its raw response parsed and delivered.

To add Volley to your project add the following dependency in your App’s build.gradle file.

compile 'com.android.volley:volley:1.0.0'

Add the following permission to your AndroidManifest.xml file.

<uses-permission android:name="android.permission.INTERNET"/>

At first make a RequestQueue, which holds the HTTP Requests in a background thread. Ideally, the RequestQueue should be made once and then referred to it across the Application. The Application is an ideal place to make it.

With our RequestQueue initialized, we’re ready to write the actual request code.

JsonObjectRequest

Volley provides JsonObjectRequest class to make JSON object request. Add the below code in onCreate() method of your Activity. Here we are fetching the JSON by making a call to url and parsing it.

String url = "http://jsonplaceholder.typicode.com/users/1";
RequestQueue requestQueue = Volley.newRequestQueue(this);

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
    Request.Method.GET,
    url,
    null,
    new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            try {
                String name = response.getString("name");
                String email = response.getString("email");

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error){
            VolleyLog.d(TAG, "Error: " + error.getMessage());
        }
    }
);

// add JsonObjectRequest to the RequestQueue
requestQueue.add(jsonObjectRequest);

JsonArrayRequest

This class can be used to retrieve JSON array but not JSON object and only HTTP GET is supported as of now. As it supports only GET, so if you are to specify some querystring parameters then append those in the URL itself. The constructor does not accept request parameters.

String url = "http://jsonplaceholder.typicode.com/users/?_limit=5";
RequestQueue requestQueue = Volley.newRequestQueue(this);

JsonArrayRequest req = new JsonArrayRequest(URL, new Response.Listener<JSONArray> () {
    @Override
    public void onResponse(JSONArray response) {
        try {
            VolleyLog.v("Response:%n %s", response.toString(4));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        VolleyLog.e("Error: ", error.getMessage());
    }
});

// add JsonArrayRequest to the RequestQueue
requestQueue.add(req);

StringRequest

This class can be used to retrieve the response from server as String, ideally you should use this class when you intend to parse the response by yourself, e.g. if it is XML. It also provides overloaded constructors to further customize your request.

In following snippet we instantiate a StringRequest that will perform a GET (the other HTTP actions are available as well) request to the url, and provide it with two listeners: onItemsLoaded and onItemsError.

String url = "http://jsonplaceholder.typicode.com/users/1";
RequestQueue requestQueue = Volley.newRequestQueue(this);

Response.Listener<String> onItemsLoaded = new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        Log.i(TAG, response);
    }
};

Response.ErrorListener onItemsError = new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        Log.e(TAG, error.toString());
    }
};

StringRequest req = new StringRequest(Request.Method.GET, url, onItemsLoaded, onItemsError);

// add StringRequest to the RequestQueue
requestQueue.add(req);

Making GET requests

Making GET Requests is simple.

String url = "http://jsonplaceholder.typicode.com/users/1";
RequestQueue requestQueue = Volley.newRequestQueue(this);

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
    Request.Method.GET,
    url,
    null,
    new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            try {
                String name = response.getString("name");
                String email = response.getString("email");

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error){
            VolleyLog.d(TAG, "Error: " + error.getMessage());
        }
    }
);

Making POST requests

For a POST request, to add form parameters/values, the getParams() method needs to be overridden and a Map needs to be returned.

String url = "http://jsonplaceholder.typicode.com/posts/";
RequestQueue requestQueue = Volley.newRequestQueue(this);

StringRequest req = new StringRequest(Request.Method.POST, url,
    new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            Log.d(TAG, response);
        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d(TAG, error.toString());
       }
    })
    {
    @Override
    protected Map<String, String> getParams() {
        Map<String, String>  params = new HashMap<String, String>();
        params.put("userId", 1);
        params.put("title", "My post");
        params.put("body", "My body");
        return params;
    }
};

requestQueue.add(req);

Making PUT requests

Creating PUT Request is same as POST basically.

String url = "http://jsonplaceholder.typicode.com/posts/1";
RequestQueue requestQueue = Volley.newRequestQueue(this);

StringRequest req = new StringRequest(Request.Method.PUT, url,
    new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            Log.d(TAG, response);
        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d(TAG, error.toString());
        }
    })
    {
    @Override
    protected Map<String, String> getParams() {
            Map<String, String>  params = new HashMap<String, String> ();
            params.put("userId", 1);
            params.put("title", "My post");
            params.put("body", "My body");
            return params;
    }
};

requestQueue.add(req);

Setting request headers (HTTP headers)

Sometimes it is necessary to add extra headers to the HTTP requests, one common case is to add an Authorization header for HTTP Basic Auth. Volley Request class provides a method called getHeaders() which you need to override to add your custom headers if necessary.

Adding custom headers:

JsonObjectRequest req = new JsonObjectRequest(url, new JSONObject(params),
    new Response.Listener<JSONObject>() {
    @Override
        public void onResponse(JSONObject response) {
            // handle response
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // handle error
        }
    })
    {
        @Override
        public Map<String, String> getHeaders() {
            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("CUSTOM_HEADER", "Hello");
            return headers;
        }
    };