• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![Life of a request](./images/volley-request.png)
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