• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Set up a RequestQueue
2
3The previous lesson showed you how to use the convenience method
4`Volley.newRequestQueue` to set up a `RequestQueue`, taking advantage of
5Volley's default behaviors. This lesson walks you through the explicit steps of creating a
6`RequestQueue`, to allow you to supply your own custom behavior.
7
8This lesson also describes the recommended practice of creating a `RequestQueue`
9as a singleton, which makes the `RequestQueue` last the lifetime of your app.
10
11## Set up a network and cache
12
13A `RequestQueue` needs two things to do its job: a network to perform transport
14of the requests, and a cache to handle caching. There are standard implementations of these
15available in the Volley toolbox: `DiskBasedCache` provides a one-file-per-response
16cache with an in-memory index, and `BasicNetwork` provides a network transport based
17on your preferred HTTP client.
18
19`BasicNetwork` is Volley's default network implementation. A `BasicNetwork`
20must be initialized with the HTTP client your app is using to connect to the network.
21Typically this is an
22[`HttpURLConnection`](https://developer.android.com/reference/java/net/HttpURLConnection).
23
24This snippet shows you the steps involved in setting up a `RequestQueue`:
25
26*Kotlin*
27
28```kotlin
29// Instantiate the cache
30val cache = DiskBasedCache(cacheDir, 1024 * 1024) // 1MB cap
31
32// Set up the network to use HttpURLConnection as the HTTP client.
33val network = BasicNetwork(HurlStack())
34
35// Instantiate the RequestQueue with the cache and network. Start the queue.
36val requestQueue = RequestQueue(cache, network).apply {
37    start()
38}
39
40val url = "http://www.example.com"
41
42// Formulate the request and handle the response.
43val stringRequest = StringRequest(Request.Method.GET, url,
44         Response.Listener<String> { response ->
45            // Do something with the response
46        },
47        Response.ErrorListener { error ->
48            // Handle error
49            textView.text = "ERROR: %s".format(error.toString())
50        })
51
52// Add the request to the RequestQueue.
53requestQueue.add(stringRequest)
54
55// ...
56```
57
58*Java*
59
60```java
61RequestQueue requestQueue;
62
63// Instantiate the cache
64Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
65
66// Set up the network to use HttpURLConnection as the HTTP client.
67Network network = new BasicNetwork(new HurlStack());
68
69// Instantiate the RequestQueue with the cache and network.
70requestQueue = new RequestQueue(cache, network);
71
72// Start the queue
73requestQueue.start();
74
75String url = "http://www.example.com";
76
77// Formulate the request and handle the response.
78StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
79        new Response.Listener<String>() {
80    @Override
81    public void onResponse(String response) {
82        // Do something with the response
83    }
84},
85    new Response.ErrorListener() {
86        @Override
87        public void onErrorResponse(VolleyError error) {
88            // Handle error
89    }
90});
91
92// Add the request to the RequestQueue.
93requestQueue.add(stringRequest);
94
95// ...
96```
97
98If you just need to make a one-time request and don't want to leave the thread pool
99around, you can create the `RequestQueue` wherever you need it and call `stop()` on the
100`RequestQueue` once your response or error has come back, using the
101`Volley.newRequestQueue()` method described in [Sending a Simple Request](./simple.md).
102But the more common use case is to create the `RequestQueue` as a
103singleton to keep it running for the lifetime of your app, as described in the next section.
104
105## Use a singleton pattern
106
107If your application makes constant use of the network, it's probably most efficient to
108set up a single instance of `RequestQueue` that will last the lifetime of your app.
109You can achieve this in various ways. The recommended approach is to implement a singleton
110class that encapsulates `RequestQueue` and other Volley functionality. Another approach is to
111subclass [`Application`](https://developer.android.com/reference/android/app/Application) and
112set up the `RequestQueue` in
113[`Application.onCreate()`](https://developer.android.com/reference/android/app/Application#onCreate()).
114But this approach is discouraged; a static singleton can provide the same functionality in a
115more modular way.
116
117A key concept is that the `RequestQueue` must be instantiated with the
118[`Application`](https://developer.android.com/reference/android/app/Application) context, not an
119[`Activity`](https://developer.android.com/reference/android/app/Activity) context. This
120ensures that the `RequestQueue` will last for the lifetime of your app, instead of
121being recreated every time the activity is recreated (for example, when the user
122rotates the device).
123
124Here is an example of a singleton class that provides `RequestQueue` and
125`ImageLoader` functionality:
126
127*Kotlin*
128
129```kotlin
130class MySingleton constructor(context: Context) {
131    companion object {
132        @Volatile
133        private var INSTANCE: MySingleton? = null
134        fun getInstance(context: Context) =
135            INSTANCE ?: synchronized(this) {
136                INSTANCE ?: MySingleton(context).also {
137                    INSTANCE = it
138                }
139            }
140    }
141    val imageLoader: ImageLoader by lazy {
142        ImageLoader(requestQueue,
143                object : ImageLoader.ImageCache {
144                    private val cache = LruCache<String, Bitmap>(20)
145                    override fun getBitmap(url: String): Bitmap? {
146                        return cache.get(url)
147                    }
148                    override fun putBitmap(url: String, bitmap: Bitmap) {
149                        cache.put(url, bitmap)
150                    }
151                })
152    }
153    val requestQueue: RequestQueue by lazy {
154        // applicationContext is key, it keeps you from leaking the
155        // Activity or BroadcastReceiver if someone passes one in.
156        Volley.newRequestQueue(context.applicationContext)
157    }
158    fun <T> addToRequestQueue(req: Request<T>) {
159        requestQueue.add(req)
160    }
161}
162```
163
164*Java*
165
166```java
167public class MySingleton {
168    private static MySingleton instance;
169    private RequestQueue requestQueue;
170    private ImageLoader imageLoader;
171    private static Context ctx;
172
173    private MySingleton(Context context) {
174        ctx = context;
175        requestQueue = getRequestQueue();
176
177        imageLoader = new ImageLoader(requestQueue,
178                new ImageLoader.ImageCache() {
179            private final LruCache<String, Bitmap>
180                    cache = new LruCache<String, Bitmap>(20);
181
182            @Override
183            public Bitmap getBitmap(String url) {
184                return cache.get(url);
185            }
186
187            @Override
188            public void putBitmap(String url, Bitmap bitmap) {
189                cache.put(url, bitmap);
190            }
191        });
192    }
193
194    public static synchronized MySingleton getInstance(Context context) {
195        if (instance == null) {
196            instance = new MySingleton(context);
197        }
198        return instance;
199    }
200
201    public RequestQueue getRequestQueue() {
202        if (requestQueue == null) {
203            // getApplicationContext() is key, it keeps you from leaking the
204            // Activity or BroadcastReceiver if someone passes one in.
205            requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
206        }
207        return requestQueue;
208    }
209
210    public <T> void addToRequestQueue(Request<T> req) {
211        getRequestQueue().add(req);
212    }
213
214    public ImageLoader getImageLoader() {
215        return imageLoader;
216    }
217}
218```
219
220Here are some examples of performing `RequestQueue` operations using the singleton
221class:
222
223*Kotlin*
224
225```kotlin
226// Get a RequestQueue
227val queue = MySingleton.getInstance(this.applicationContext).requestQueue
228
229// ...
230
231// Add a request (in this example, called stringRequest) to your RequestQueue.
232MySingleton.getInstance(this).addToRequestQueue(stringRequest)
233```
234
235*Java*
236
237```java
238// Get a RequestQueue
239RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()).
240    getRequestQueue();
241
242// ...
243
244// Add a request (in this example, called stringRequest) to your RequestQueue.
245MySingleton.getInstance(this).addToRequestQueue(stringRequest);
246```
247