Updated 7 days ago | GitHub

Networking with the Volley Library

Overview

Volley is a library that makes networking for Android apps easier and most importantly, faster. Volley Library was announced by Ficus Kirkpatrick at Google I/O ’13.
It was first used by the Play Store team in Play Store Application and then they released it as an open source library. Although it was originally hosted within the Android Open Source Project (AOSP), Volley now lives as a standalone library at google/volley on GitHub.

Current status: Volley is effectively in maintenance mode — its last release was 1.2.1 on 2021-08-25, and the repository has seen only occasional housekeeping commits since. It remains supported for existing apps and the official training guide is still published, but for new projects most teams use OkHttp or Retrofit, which are actively developed and pair naturally with Kotlin coroutines. Volley’s remaining niche is apps that want its built-in request queueing, prioritization, and transparent response caching without adopting a larger networking stack.

Why Volley?

  • Volley can pretty much do everything that has to do with Networking in Android.
  • Volley automatically schedules all network requests such as fetching responses for image from web.
  • Volley provides transparent disk and memory caching.
  • Volley provides powerful cancellation request API for canceling a single request or you can set blocks of requests to cancel.
  • Volley provides powerful customization abilities.
  • Volley provides debugging and tracing tools.

Setup Volley

Adding Volley to our app/build.gradle file:

dependencies {
    implementation 'com.android.volley:volley:1.2.1'
}

And add the internet permission in AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.simplenetworking"
    android:versionCode="1"
    android:versionName="1.0" >
 
   <!-- Add permissions here -->
   <uses-permission android:name="android.permission.INTERNET" /> 
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

</manifest>

How to use Volley?

Volley has two classes that you will have to deal with:

  1. RequestQueue - Requests are queued up here to be executed
  2. Request (and any extension of it) - Constructing a network request

A Request object comes in three major types:

  • JsonObjectRequest — To send and receive JSON Object from the server
  • JsonArrayRequest — To receive JSON Array from the server
  • ImageRequest - To receive an image from the server
  • StringRequest — To retrieve response body as String (ideally if you intend to parse the response by yourself)

Constructing a RequestQueue

All requests in Volley are placed in a queue first and then processed, here is how you will be creating a request queue:

public class MainActivity extends Activity {
	private RequestQueue mRequestQueue;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main_screen_layout);
		// ...
		mRequestQueue = Volley.newRequestQueue(this);
	}
}
class MainActivity : Activity() {
    private lateinit var requestQueue: RequestQueue

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_screen_layout)
        // ...
        requestQueue = Volley.newRequestQueue(this)
    }
}

Creating a Singleton Queue

See this guide for creating a singleton to use for sending requests.

Requesting images

Volley provides the ability to make image requests and receive back as bitmap. You can use this bitmap to set directly onto an ImageView.

ImageRequest imageRequest = new ImageRequest("https://i.imgur.com/Nwk25LA.jpg",
    new Response.Listener<Bitmap>() {
        @Override
        public void onResponse(Bitmap response) {

        }
    },
    // Image width & height equal to 0 means decode at the natural size
    0, 0,
    // ImageView scale type
    ImageView.ScaleType.FIT_XY,
    // ARGB_8888 stores each pixel on 4 bytes (8 bits per channel)
    Bitmap.Config.ARGB_8888,
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            error.printStackTrace();
        }
    });

Volley’s callback interfaces are Java SAM interfaces, so Kotlin can pass lambdas directly:

val imageRequest = ImageRequest("https://i.imgur.com/Nwk25LA.jpg",
    { response: Bitmap ->
        // use the bitmap, e.g. imageView.setImageBitmap(response)
    },
    // Image width & height equal to 0 means decode at the natural size
    0, 0,
    // ImageView scale type
    ImageView.ScaleType.FIT_XY,
    // ARGB_8888 stores each pixel on 4 bytes (8 bits per channel)
    Bitmap.Config.ARGB_8888,
    { error -> error.printStackTrace() }
)

Accessing JSON Data

After this step you are ready to create your Request objects which represents a desired request to be executed. Then we add that request onto the queue.

public class MainActivity extends Activity {
	private RequestQueue mRequestQueue;

        // ...

	private void fetchJsonResponse() {
		// Pass the third argument (the request body) as "null" for GET requests
		JsonObjectRequest req = new JsonObjectRequest(Request.Method.GET, "https://api.github.com/users/octocat", null,
		    new Response.Listener<JSONObject>() {
		        @Override
		        public void onResponse(JSONObject response) {
		            try {
		                String result = "The user's name is " + response.getString("name");
		                Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
		            } catch (JSONException e) {
		                e.printStackTrace();
		            }
		        }
		    }, new Response.ErrorListener() {
		        @Override
		        public void onErrorResponse(VolleyError error) {
		            VolleyLog.e("Error: ", error.getMessage());
		        }
		});

		/* Add your Requests to the RequestQueue to execute */
		mRequestQueue.add(req);
	}
}
class MainActivity : Activity() {
    private lateinit var requestQueue: RequestQueue

    // ...

    private fun fetchJsonResponse() {
        // Pass the third argument (the request body) as "null" for GET requests
        val req = JsonObjectRequest(Request.Method.GET, "https://api.github.com/users/octocat", null,
            { response ->
                try {
                    val result = "The user's name is " + response.getString("name")
                    Toast.makeText(this@MainActivity, result, Toast.LENGTH_SHORT).show()
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
            },
            { error -> VolleyLog.e("Error: ", error.message) }
        )

        /* Add your Requests to the RequestQueue to execute */
        requestQueue.add(req)
    }
}

And that will execute the request to the server and respond back with the result as specified in the Response.Listener callback. For a more detailed look at Volley, check out this volley tutorial.

Canceling Requests

You can tag a request with:

StringRequest stringRequest = ...;
RequestQueue mRequestQueue = ...;

// Set the tag on the request.
stringRequest.setTag(TAG);

// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
val stringRequest: StringRequest = ...
val requestQueue: RequestQueue = ...

// Set the tag on the request.
stringRequest.tag = TAG

// Add the request to the RequestQueue.
requestQueue.add(stringRequest)

You can now cancel all requests with this tag using the cancelAll on the request queue:

@Override
protected void onStop() {
    super.onStop();
    if (mRequestQueue != null) {
        mRequestQueue.cancelAll(TAG);
    }
}
override fun onStop() {
    super.onStop()
    requestQueue.cancelAll(TAG)
}

Using with OkHttp

An earlier version of this guide showed a HurlStack subclass whose createConnection(URL url) override returned client.open(url). That integration no longer compiles: OkHttpClient.open(URL) was an OkHttp 1.x API removed in OkHttp 2.0 (2014-06-21) in favor of OkUrlFactory, and OkUrlFactory was itself deleted in OkHttp 3.14 (2019-03-14) — no current OkHttp release exposes an HttpURLConnection-compatible surface for a HurlStack override to delegate to.

Volley’s supported extension point for a custom transport is BaseHttpStack, passed in via Volley.newRequestQueue(Context, BaseHttpStack) (the older HttpStack overload is deprecated). The official Volley documentation neither ships nor documents an OkHttp-backed stack, so wiring OkHttp underneath Volley today means writing and maintaining your own BaseHttpStack implementation. In practice, if you want OkHttp’s features (HTTP/2, connection pooling, interceptors), use OkHttp or Retrofit directly rather than routing them through Volley.

Troubleshooting

You can enable verbose logging by simply setting VolleyLog.DEBUG to be true before issuing network requests:

VolleyLog.DEBUG = true;
VolleyLog.DEBUG = true

You can also activate verbose logging after an app has already been running by typing this command using the Android Debug Shell (ADB):

adb shell setprop log.tag.Volley VERBOSE

The output will show cache hits, queue additions, and network latency calls:

03-13 23:32:11.382 2565-2565/com.test D/Volley: [1] MarkerLog.finish: (1494 ms) [ ] https://i.imgur.com/Nwk25LA.jpg 0x189700ee LOW 1
03-13 23:32:11.382 2565-2565/com.test D/Volley: [1] MarkerLog.finish: (+0   ) [ 1] add-to-queue
03-13 23:32:11.382 2565-2565/com.test D/Volley: [1] MarkerLog.finish: (+85  ) [191] cache-queue-take
03-13 23:32:11.382 2565-2565/com.test D/Volley: [1] MarkerLog.finish: (+107 ) [191] cache-hit
03-13 23:32:11.383 2565-2565/com.test D/Volley: [1] MarkerLog.finish: (+957 ) [191] cache-hit-parsed
03-13 23:32:11.383 2565-2565/com.test D/Volley: [1] MarkerLog.finish: (+0   ) [191] post-response
03-13 23:32:11.383 2565-2565/com.test D/Volley: [1] MarkerLog.finish: (+345 ) [ 1] done

References