Volley, a Networking Library for Android

Valdio Veliu
Valdio Veliu
Share
This article was updated on 21st December, 2016. Specifically: new entry, updated deprecated code and added a new section for image loading.

Networking with Volley in Android

Networking has been around since day zero of mobile technologies and Android is not different. What has changed is the way network operations are handled. The focus of networking libraries such as Volley has been the automation of the network operations.

Until HoneyComb, network calls ran from the main thread and in subsequent Android versions, network requests executed asynchronously from the main thread. To make a network call, a developer needs to implement an Asynctask in a different thread from the main application thread or a NetworkOnMainThreadException will be thrown.

A short overview of Volley

Volley is a networking library for Android that manages network requests. It bundles the most important features you’ll need, such as accessing JSON APIs, loading images and String requests in an easier-to-use package.

By using Volley for network operations you avoid the standard way to handle networking, HttpURLConnection. Another reason is asynchronicity. Volley handles asynchronicity by itself, there is no need to create Asynctask manually.

Based on the documentation, the core of every network operation performed by Volley is the RequestQueue. Working with Volley is handled by creating a RequestQueue and passing it Request objects. The RequestQueue manages worker threads for running the network operations, reading from and writing to the cache, and parsing responses.

Volley offers a variety of features, as mentioned in its documentation:

  1. Automatic scheduling of network requests.
  2. Multiple concurrent network connections.
  3. Caching.
  4. Request prioritization.
  5. Cancellation of ongoing API requests.

These are the core benefits that this library provides and the main focus of this article.

Import Volley, add Permissions

Before getting started with Volley, you need to configure your Android project.
Create a new Android project. Open build.gradle(Module: app) and add the following dependency.

dependencies {
    //...

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

In AndroidManifest.xml add the internet permission.

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

Standard Network Requests

As I previously mentioned, the core of every network operation performed by Volley is the RequestQueue. Every request made to the network is passed to the RequestQueue trough Request objects.
There are three types of requests, JSON requests, Image requests and String requests. I will go through each of these types with explanations and code examples.

For now, in MainActivity’s onCreate() method, initiate the RequestQueue.

    RequestQueue requestQueue;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //...
        requestQueue = Volley.newRequestQueue(this); // 'this' is the Context

    }

JSON Requests

Volley has Requests for JSONObject and JSONArray. The structure of JSONRequest and most of the request classes included in Volley uses constructors like the following.

JsonObjectRequest request JsonObjectRequest(RequestMethod, URL, null,  new ResponseListener(), new ErrorListener());

Parameters passed into the constructor:

  • RequestMethod (GET, POST, PUT, DELETE, etc.)
  • URL: String of the URL of the required object
  • JSONObject: An optional object posted with the request, null if there is no object posted
  • ResponseListener: Response Listener, whose callback method will contain the response
  • ErrorListener: A Response.ErrorListener whose callback method will contain any problem with the request.

The following code snippets are the complete implementation of both JsonObjectRequest and JsonArrayRequest respectively.

        /*Json Request*/
   String url = "https://json_url/";
   JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null,
           new Response.Listener<JSONObject>() {
               @Override
               public void onResponse(JSONObject response) {

               }
           },
           new Response.ErrorListener() {
               @Override
               public void onErrorResponse(VolleyError error) {

               }
           });
   //add request to queue
   requestQueue.add(jsonObjectRequest);

   JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null,
           new Response.Listener<JSONArray>() {
               @Override
               public void onResponse(JSONArray response) {

               }
           },
           new Response.ErrorListener() {
               @Override
               public void onErrorResponse(VolleyError error) {

               }
           });
   //add request to queue
   requestQueue.add(jsonArrayRequest);

Now that I’ve shown how to receive JSON data in Android, let’s see how to post data with Volley.

The request is the same format as receiving JSON data with the exception that you must specify a JSONObject posted with the request and request headers for sending data from the client to server side.

    /*Post data*/
    Map<String, String> jsonParams = new HashMap<String, String>();

jsonParams.put("email", "user@gmail.com");
jsonParams.put("username", "user");
jsonParams.put("password", "pass");

    JsonObjectRequest postRequest = new JsonObjectRequest( Request.Method.POST, URL,

          new JSONObject(jsonParams),
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                  //   Handle Error
                }
            }) {
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("Content-Type", "application/json; charset=utf-8");
            headers.put("User-agent", System.getProperty("http.agent"));
            return headers;
        }
    };
requestQueue.add(postRequest);

Note that the request headers might have to change depending on the development use case.

String Request

This type of request is used to retrieve data from a server as a String.

   /*String Request*/
   String url = "https://string_url/";
   StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
           new Response.Listener<String>() {
               @Override
               public void onResponse(String response) {

               }
           },
           new Response.ErrorListener() {
               @Override
               public void onErrorResponse(VolleyError error) {

               }
           });
   //add request to queue
   requestQueue.add(stringRequest);

The structure of the StringRequest contains a request method (POST or GET), a URL to the String source, a Response.Listener and a Response.ErrorListener. Pretty much the same as the JsonRequest.

Image Request

Volley offers a few ways to load images in Android. I will go through all of them to explain their differences and provide some code samples.

ImageRequest

ImageRequest is a way to load images for getting an image at a given URL. The structure of this network call is similar to the other requests previously presented.
The following code is an example of an ImageRequest to load an image into an ImageView.

   int maxWidth = ...;
   int maxHeight = ...;
   String URL = "http://image_url.png";
   ImageRequest imageRequest = new ImageRequest(URL, new Response.Listener<Bitmap>() {
       @Override
       public void onResponse(Bitmap response) {
           // Assign the response to an ImageView
           ImageView imageView = (ImageView) findViewById(R.id.imageView);
           imageView.setImageBitmap(response);
       }
   }, maxWidth, maxHeight, null);
   //add request to queue
   requestQueue.add(imageRequest);

The structure of the ImageRequest is straightforward. It needs the image’s URL, a Response Listener, whose callback method will contain the image Bitmap as a response, a maxWidth and maxHeight, a Config format to decode the bitmap to, and a Response.ErrorListener for any response errors. Add the request to the RequestQueue and the Android runtime will handle the rest.

ImageLoader

ImageLoader is a helper class to handle loading and caching images from remote URLs. This request is useful for a large number of ImageRequest. According to the documentation ImageLoader provides an in-memory cache to sit in front of the normal Volley cache, which is important to prevent flickering.

NetworkImageView

NetworkImageView is an efficient way to replace ImageView when images are being loaded from the network.

The following code snippets provide an implementation of both the two last sections of image loading with Volley. The following VolleySingleton class is an implementation of a RequestQueue. This singleton class has caching capabilities with in-memory LRU cache. The LruCache is set up to store up to 30 elements.

import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.util.Log;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;

public class VolleySingleton {
    private static VolleySingleton singletonInstance = null;
    private RequestQueue requestQueue;
    private ImageLoader imageLoader;

    private VolleySingleton(Context context) {
        requestQueue = Volley.newRequestQueue(context);
        imageLoader = new ImageLoader(this.requestQueue, new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap> lruCache = new LruCache<String, Bitmap>(30);
            //30 -> the maximum number of entries in the cache.

            public void putBitmap(String url, Bitmap bitmap) {
                lruCache.put(url, bitmap);
                Log.d("CachedItems", String.valueOf(lruCache.size()));
            }

            public Bitmap getBitmap(String url) {
                return lruCache.get(url);
            }
        });
    }

    public static VolleySingleton getInstance(Context context) {
        if (singletonInstance == null) {
            singletonInstance = new VolleySingleton(context);
        }
        return singletonInstance;
    }

    public RequestQueue getRequestQueue() {
        return this.requestQueue;
    }

    public ImageLoader getImageLoader() {
        return this.imageLoader;
    }
}

Now that the VolleySingleton class is setup, lets load an image into a NetworkImageView. But first, add an instance int the Activity’s layout file. Here is an example:

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/networkImageView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

Finally, load an image into the NetworkImageView. In the in MainActivity’s onCreate() method add this code.

    private ImageLoader imageLoader;
    private NetworkImageView imageView;
    private static final String IMAGE_URL = "https://the_images_url.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //...

        imageLoader = VolleySingleton.getInstance(getApplicationContext()).getImageLoader();
        imageView = (NetworkImageView) findViewById(R.id.networkImageView);
        imageView.setImageUrl(IMAGE_URL, imageLoader);

    }

To make sure the cache works properly, I added a Log statement in the VolleySingleton class. Run the project and check the Log in Android Studio. Each time a new image is cached the device prints out a number of cached items.

Request Prioritization

Handling network requests means prioritizing what’s needed and how fast the response is needed since networking is a real time operation.

Volley processes the requests from higher priorities to lower priorities, in first-in-first-out order. There is no setPriority() method, so to prioritize a request, some work is needed.

Here is an example of a custom JsonObjectRequest class that can make priority requests. The focus of this class is on the overridden getPriority() method. When the request is added to the queue this method will return the priority assigned to it by setPriority(), or will return Priority.HIGH assigned inside the class, but it won’t search for a priority outside this class.

The same structure applies to all the other request types.

public class CustomPriorityRequest extends JsonObjectRequest {

    Priority priority = Priority.HIGH;

    public CustomPriorityRequest(int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
        super(method, url, jsonRequest, listener, errorListener);
    }

    public CustomPriorityRequest(String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
        super(url, jsonRequest, listener, errorListener);
    }

    @Override
    public Priority getPriority() {
        return priority;
    }

    public void setPriority(Priority p){
        priority = p;
    }
}

Making a request with this new class is the same as the standard requests. You have the ability to set a request priority before adding it to the queue.

   CustomPriorityRequest customPriorityRequest = new CustomPriorityRequest(
           Request.Method.GET, URL, null,
           new Response.Listener<JSONObject>(),
           new Response.ErrorListener());

   customPriorityRequest.setPriority(Request.Priority.IMMEDIATE);
   requestQueue.add(customPriorityRequest);

Some available priorities are: Priority.LOW, Priority.NORMAL, Priority.HIGH and Priority.IMMEDIATE.

Cancel Requests

Another useful tool in Volley is the ability to cancel the requests. Canceling requests is useful when the user closes the app or performs an action that results in not using the responses of the Volley requests. There is no sense executing the remaining requests in the queue, so we cancel them in the onStop() method.

The easiest way to cancel requests in Volley is to add a tag to the request and when the queued requests need to be canceled, call the cancelAll() method. This will cancel all the requests specified with that specific tag.

request.setTag("TAG");

requestQueue.cancelAll("TAG");

Once cancelAll() executes from the main thread, the remaining responses will not be delivered.

Frequently Asked Questions (FAQs) about Volley, a Networking Library for Android

What are the main advantages of using Volley over other networking libraries for Android?

Volley is a networking library developed by Google that provides several benefits over other libraries. It simplifies the process of fetching and parsing network data into your app. Volley automatically schedules all network requests, handles caching, and allows for prioritization of requests, making it an efficient choice for high-speed networking. It also provides a powerful cancellation request API for canceling single or multiple requests, and it supports request prioritization which is useful for improving the user experience in data-intensive applications.

How does Volley handle image loading and caching?

Volley provides a built-in mechanism for image loading and caching. It includes the ImageLoader class which allows for memory caching of images. This means that once an image has been loaded from a network, it is stored in the cache. The next time the same image is requested, it is retrieved from the cache instead of being downloaded again, saving bandwidth and improving performance.

Can I use Volley for large download or streaming operations?

While Volley is excellent for small network operations, it is not the best choice for large download or streaming operations. Volley holds all responses in memory during parsing, so for large download operations or streams, consider using DownloadManager or a library like OkHttp.

How can I cancel a request in Volley?

Volley provides a powerful API for canceling requests. You can cancel a single request using the cancel() method of the Request class. If you want to cancel all requests in a queue, you can call the cancelAll() method of the RequestQueue class.

How does Volley handle network retries and backoff?

Volley has a built-in mechanism for automatic retries and exponential backoff. If a network request fails, Volley will automatically retry the request with an increased timeout. The retry policy can be customized according to your needs.

How can I add a request to the Volley RequestQueue?

To add a request to the Volley RequestQueue, you first need to create a RequestQueue instance. Then, you can add your request to this queue using the add() method.

How can I customize Volley’s default behavior?

Volley is highly customizable. You can extend the Request class to define your own requests, and you can implement your own cache mechanism by extending the Cache class. You can also customize the retry policy and the priority of requests.

How does Volley handle POST and GET requests?

Volley provides the StringRequest and JsonObjectRequest classes for handling POST and GET requests. You can override the getParams() method to set the parameters for your request.

Can I use Volley with Kotlin?

Yes, you can use Volley with Kotlin. Volley is a Java library, but it can be used with Kotlin through the Java Interoperability feature of Kotlin.

How can I debug network requests in Volley?

Volley provides a debug logging mechanism which can be enabled by setting the DEBUG flag in the VolleyLog class to true. This will log the details of all network requests and responses.