At Google I/O, Google debuted the new, hip way to make network requests within an Android application by introducing the world to the Volley Networking Library. Like most new, hip toys these days Volley is fast, easy to use, and has ton of features. However, in many ways Volley is like a muscle car that came without instructions. This is due largely to the lack of documentation. Without the confidence and reassurance that documentation provides developers, an unwillingness to implement Volley exists, yet most everyone remains excited about Volley's future. If you haven't gotten a chance to check out the Volley Library or watch the Google I/O Volley Presentation (also shown at the bottom of this post), I encourage you to do so. At the time of this post, these two means are your best sources of information on the Volley Library.

What is Volley?

In short, Volley is a networking library that manages network requests and their response caches without the developer having to write a lot of "boilerplate" code. Volley implements tools that allow for simultaneous requests to run on a pool of threads that can be given priority over one another. All of this is done, while implementing a transparent cache that allows for quick reloading of data. It is, however, not for everything. Responses are delivered whole in memory, so it is less than ideal for large downloads such as music and movies. It is alternatively geared towards smaller requests such as JSON files, images, and other files of that size and nature.

Volley in Action

So now that you know what Volley is, you are probably ready to see it in action. The sample application included with this post demos a few of the most important features that Volley provides. It does include the utilization of a Network Image View and a bitmap cache; however, these will not be a topic of discussion in this series of posts. If you would like to learn more about the implementation of the Network Image View and a bitmap cache, I encourage you to read my colleague's post, Goole I/O 2013: Volley Image Cache Tutorial, and download his sample application.

The Sample Application

The sample application included utilizes all the tools that will be discussed in this post. The application contains four buttons each of which employs some Volley tools in a different manner. The first button, the SimpleRequestActivity, samples the building of your own custom request class by extending one of the supplied Volley request classes, setting the priority of a request, and utilizing the Volley response cache. The second button, the ImageRequestActivity, samples the use of the Volley ImageLoader. The third button, the JsonSearchRequestActivity, samples the usage of a JSONObject request, parsing a response with GSON Library, and setting and retrieving cookies. Finally, the fourth button, the NetworkImageSearchActivity, samples how to utilize the NetworkImageView in combination with a JSONObject request, whose response is being parsed by the GSON Library and being set to a list view. The list view elements each contain a different NetworkImageView whose image url is being set based on the response of the JSONObject request and all utilize a BitmapLRUCache.

Forming a Request

With Volley, network communication is managed by the RequestQueue. The best way to utilize the RequestQueue and all of its tools, especially the cache, is by instantiating it once and keeping it around as a singleton. At this point you can then add or cancel requests, stop or start requests, and access the response cache(s).

RequestQueue queue =Volley.newRequestQueue(this);

Once the RequestQueue has been instantiated a request must be formed. This can be done utilizing a few different "out of the box" request classes included with the Volley Library or by extending Volley's request class into your own custom request. The request classes already included in Volley are a String request, JSON requests, and an Image Request. Most of the request classes included in Volley library utilize constructors much like the one below.

Parameters being passed into constructor:

  • RequestMethod(get, post, delete, ect)
  • JSONObject-An optional object that will be posted with your request
  • ResponseListener- Where your data will go after the request is complete
  • ErrorListener – What will be told when there was a problem with your request.
JsonObjectRequest request JsonObjectRequest(Requestmethod, url, null, new ResponseListener(), new ErrorListener());

Response and Error Listeners

Before our request can be made, we need to create response and error classes that implement listeners so that they can be passed into our request. These listeners will be what is notified when our request has been completed or in the event of an error. When making more than one request, I like to use different response classes for the different requests but the same error class for all the requests depending on the importance of the data and if the user should be notified of an error or not. Inside the listeners, you can define a specific action to be made once the request has either succeeded or failed.

Successful Response Listener

private class ResponseListener implements Response.Listener{
 @Override
 public void onResponse(JSONObject response){

 }
}

Error Response Listener

private class ErrorListener implements Response.ErrorListener{
 @Override
 public void onErrorResponse(VolleyError error){

 }
}

Making the Call

Now, that we have made our request and response classes we are ready to add the request to the queue and retrieve the data. To do so we simply add the request to the queue.

queue.add(request);

The response or error will then be delivered to the response/error classes that we defined in our request. You can add as many requests to the queue that you would like at one time and the responses will be delivered to their respective response/error classes

Request Prioritization

If you choose to add many requests to the queue at one time you can also prioritize and order when the request will be made so that you will likely get back the most important information first. Unfortunately, Volley hasn't included a setPriority() method yet. However, with the customization that the library allows one can easily implement this themself my extending the request class and overriding the getPriority() method and implementing a setPriority() method. Below is the example prioritization implementation included with the attached sample application.

public class CustomStringRequest extends StringRequest {
 private Priority priority = Priority.LOW;

 CustomStringRequest(String url, Listenerstring>listener,ErrorListener errorListener) { string>
 super(url, listener, errorListener);
 }

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

 public void setPriority(Priority priority){
 this.priority = priority;
 }
}

The above class sets your default priority to low, and the below line changes this to immediate from the activity that instantiates the request.

Request.setPriority(Priority.IMMEDIATE);

Utilizing the Response Cache

The cache is implemented automatically for requests such as JSON Requests or other requests that extend the Volley Request class. You do, however, have the option of turning the cache off for a specific request by passing the below line of code before adding it to the queue.

request.setShouldCache(false);

Accessing the cache

Once a successful response has been received and cached, it will likely result in a better user experience if the cached response is used in the event that the same request is made again rather than making a new call to the network. This can be done in either of following manners:

request.getCacheEntry().data

This method is done after a request has been formed and can be a last check before you add it to the queue and the call is made.

queue.getCache().get(url).data

This method retrieves the cache through the RequestQueue by passing the request key, which by default is the request's url. This method is handy in the event that you would like to check for a cached response before you have created the request. If you have kept your queue around as a singleton this method becomes even more useful, allowing you to retrieve cached responses from other activity requests and prior application runs.

Volley Cache Tools

The Volley cache implementation also allows you to remove a single cached response, clear the entire cache, mark a cached responses as invalid, or retrieve the date of a cached response so that you can accurately decide when an update should be made. In the sample application, I let the user remove the cache of a specific request by clicking a button.

queue.getCache().remove(url);

Rather than having to do this for each request when we want to clear the entire cache Volley provides a much faster way.

queue.getCache().clear();

For efficiency and battery saving purposes, it is sometimes necessary to make multiple calls at once rather than performing them sporadically. In this situation we might have data that needs updated, but isn't so important that it needs to happen at this moment. It would be better to wait and update the response with the next important network call or when enough of them have been marked as invalid. We can just simply invalidate the cached response of a specific request without deleting it from the cache. This allows us to keep using this data until a new call is made and the cached response is overridden with the new response.

queue.getCache().invalidate(url, true);

Lastly, you can also get the date for when the response was originally received. This is nice to have around to be sure that your user's data is never too old, but you aren't inefficiently making requests to the network.

queue.getCache().get(url).serverDate

These methods can be used in conjunction with a test case that would add the request to the queue only if the cache does not exist, is marked as invalid, or is too far out of date.

if(queue.getCache().get(url)!=null){
 //response exists
 String cachedResponse = new String(queue.getCache().get(url).data);
 results.setText("From Cache: " + cachedResponse);
}else{
 //no response
 queue.add(stringRequest);
}

Cookies

Storing and retrieving cookies requires a little bit different usage of the RequestQueue. Rather than just implementing the queue by passing the context to the queue's constructor you will also need to pass an HttpClientStack containing an AbstractHttpClient.

AbstractHttpClient client;
queue = Volley.newRequestQueue(this, new HttpClientStack(client));

As a result of this, we lose one of Volley's greatest features, which is making multiple requests at once. This is due to the fact that we are including an HttpClient and we have to live by its rules and let one connection close before we introduce another one. Once again, this would be best utilized by instantiating it once and keeping it around as a singleton. After we have instantiated our queue in this manner, all we have to do now is add cookies to the client in the typical fashion.

CookieStore store = client.getCookieStore();

//add our own cookie for demo purposes
Cookie cookie = new BasicClientCookie("Example_Cookie", "80");
store.addCookie(cookie);

Conclusion

Though the Volley Networking Library is not perfect, it does provide a streamlined approach to retrieving data from the network. As the Volley adoption rate continues to grow and more utilization methods and techniques form, Volley will likely be used by Android Developers on a regular basis. Conversely, Volley's role in major production applications is yet to be foreseen. I encourage you to download the included sample application and try Volley yourself. Simply download the Sample Application and the Volley Library, add the library to the downloaded project, and run the application.