1# Send a simple request 2 3At a high level, you use Volley by creating a `RequestQueue` and passing it 4`Request` objects. The `RequestQueue` manages worker threads for running the 5network operations, reading from and writing to the cache, and parsing responses. Requests 6do the parsing of raw responses and Volley takes care of dispatching the parsed response 7back to the main thread for delivery. 8 9This lesson describes how to send a request using the `Volley.newRequestQueue` 10convenience method, which sets up a `RequestQueue` for you. 11See the next lesson, [Setting Up a RequestQueue](./requestqueue.md), for information on how to set 12up a `RequestQueue` yourself. 13 14This lesson also describes how to add a request to a `RequestQueue` and cancel a 15request. 16 17## Add the INTERNET permission 18 19To use Volley, you must add the 20[`android.permission.INTERNET`](https://developer.android.com/reference/android/Manifest.permission#INTERNET) 21permission to your app's manifest. Without this, your app won't be able to connect to the network. 22 23## Use newRequestQueue 24 25Volley provides a convenience method `Volley.newRequestQueue` that sets up a 26`RequestQueue` for you, using default values, and starts the queue. For example: 27 28*Kotlin* 29 30```kotlin 31val textView = findViewById<TextView>(R.id.text) 32// ... 33 34// Instantiate the RequestQueue. 35val queue = Volley.newRequestQueue(this) 36val url = "https://www.google.com" 37 38// Request a string response from the provided URL. 39val stringRequest = StringRequest(Request.Method.GET, url, 40 Response.Listener<String> { response -> 41 // Display the first 500 characters of the response string. 42 textView.text = "Response is: ${response.substring(0, 500)}" 43 }, 44 Response.ErrorListener { textView.text = "That didn't work!" }) 45 46// Add the request to the RequestQueue. 47queue.add(stringRequest) 48``` 49 50*Java* 51 52```java 53final TextView textView = (TextView) findViewById(R.id.text); 54// ... 55 56// Instantiate the RequestQueue. 57RequestQueue queue = Volley.newRequestQueue(this); 58String url = "https://www.google.com"; 59 60// Request a string response from the provided URL. 61StringRequest stringRequest = new StringRequest(Request.Method.GET, url, 62 new Response.Listener<String>() { 63 @Override 64 public void onResponse(String response) { 65 // Display the first 500 characters of the response string. 66 textView.setText("Response is: " + response.substring(0,500)); 67 } 68}, new Response.ErrorListener() { 69 @Override 70 public void onErrorResponse(VolleyError error) { 71 textView.setText("That didn't work!"); 72 } 73}); 74 75// Add the request to the RequestQueue. 76queue.add(stringRequest); 77``` 78 79Volley always delivers parsed responses on the main thread. Running on the main thread 80is convenient for populating UI controls with received data, as you can freely modify UI 81controls directly from your response handler, but it's especially critical to many of the 82important semantics provided by the library, particularly related to canceling requests. 83 84See [Setting Up a RequestQueue](requestqueue.md) for a 85description of how to set up a `RequestQueue` yourself, instead of using the 86`Volley.newRequestQueue` convenience method. 87 88## Send a request 89 90To send a request, you simply construct one and add it to the `RequestQueue` with 91`add()`, as shown above. Once you add the request it moves through the pipeline, 92gets serviced, and has its raw response parsed and delivered. 93 94When you call `add()`, Volley runs one cache processing thread and a pool of 95network dispatch threads. When you add a request to the queue, it is picked up by the cache 96thread and triaged: if the request can be serviced from cache, the cached response is 97parsed on the cache thread and the parsed response is delivered on the main thread. If the 98request cannot be serviced from cache, it is placed on the network queue. The first 99available network thread takes the request from the queue, performs the HTTP transaction, 100parses the response on the worker thread, writes the response to cache, and posts the parsed 101response back to the main thread for delivery. 102 103Note that expensive operations like blocking I/O and parsing/decoding are done on worker 104threads. You can add a request from any thread, but responses are always delivered on the 105main thread. 106 107This figure illustrates the life of a request: 108 109 110 111## Cancel a request 112 113To cancel a request, call `cancel()` on your `Request` object. Once cancelled, 114Volley guarantees that your response handler will never be called. What this means in 115practice is that you can cancel all of your pending requests in your activity's 116[`onStop()`](https://developer.android.com/reference/android/app/Activity#onStop()) 117method and you don't have to litter your response handlers with checks for `getActivity() == null`, 118whether `onSaveInstanceState()` has been called already, or other defensive 119boilerplate. 120 121To take advantage of this behavior, you would typically have to 122track all in-flight requests in order to be able to cancel them at the 123appropriate time. There is an easier way: you can associate a tag object with each 124request. You can then use this tag to provide a scope of requests to cancel. For 125example, you can tag all of your requests with the 126[`Activity`](https://developer.android.com/reference/android/app/Activity) 127they are being made on behalf of, and call `requestQueue.cancelAll(this)` from 128[`onStop()`](https://developer.android.com/reference/android/app/Activity#onStop()). 129Similarly, you could tag all thumbnail image requests in a 130[`ViewPager`](https://developer.android.com/reference/androidx/viewpager/widget/ViewPager) 131tab with their respective tabs and cancel on swipe 132to make sure that the new tab isn't being held up by requests from another one. 133 134Here is an example that uses a string value for the tag: 135 1361. Define your tag and add it to your requests. 137 138 *Kotlin* 139 140 ```kotlin 141 val TAG = "MyTag" 142 val stringRequest: StringRequest // Assume this exists. 143 val requestQueue: RequestQueue? // Assume this exists. 144 145 // Set the tag on the request. 146 stringRequest.tag = TAG 147 148 // Add the request to the RequestQueue. 149 requestQueue?.add(stringRequest) 150 ``` 151 152 *Java* 153 154 ```java 155 public static final String TAG = "MyTag"; 156 StringRequest stringRequest; // Assume this exists. 157 RequestQueue requestQueue; // Assume this exists. 158 159 // Set the tag on the request. 160 stringRequest.setTag(TAG); 161 162 // Add the request to the RequestQueue. 163 requestQueue.add(stringRequest); 164 ``` 165 1662. In your activity's [`onStop()`](https://developer.android.com/reference/android/app/Activity#onStop()) 167 method, cancel all requests that have this tag. 168 169 *Kotlin* 170 171 ```kotlin 172 protected fun onStop() { 173 super.onStop() 174 requestQueue?.cancelAll(TAG) 175 } 176 ``` 177 178 *Java* 179 180 ```java 181 @Override 182 protected void onStop() { 183 super.onStop(); 184 if (requestQueue != null) { 185 requestQueue.cancelAll(TAG); 186 } 187 } 188 ``` 189 190Take care when canceling requests. If you are depending on your response handler to 191advance a state or kick off another process, you need to account for this. Again, the 192response handler will not be called. 193