blob: 6858d91e6eac6abfb6d9432d8f9821d69fae5316 [file] [log] [blame]
Katie McCormick1a89ae42014-03-18 17:13:50 -07001page.title=Setting Up a RequestQueue
2
3trainingnavtop=true
4
5@jd:body
6
7<div id="tb-wrapper">
8<div id="tb">
9
10<!-- table of contents -->
11<h2>This lesson teaches you to</h2>
12<ol>
13 <li><a href="#network">Set Up a Network and Cache</a></li>
14 <li><a href="#singleton">Use a Singleton Pattern</a></li>
15</ol>
16
17</div>
18</div>
19
20<a class="notice-developers-video wide" href="https://developers.google.com/events/io/sessions/325304728">
21<div>
22 <h3>Video</h3>
23 <p>Volley: Easy, Fast Networking for Android</p>
24</div>
25</a>
26
27
28<p>The previous lesson showed you how to use the convenience method
29<code>Volley.newRequestQueue</code> to set up a {@code RequestQueue}, taking advantage of
30Volley's default behaviors. This lesson walks you through the explicit steps of creating a
31{@code RequestQueue}, to allow you to supply your own custom behavior.</p>
32
33<p>This lesson also describes the recommended practice of creating a {@code RequestQueue}
34as a singleton, which makes the {@code RequestQueue} last the lifetime of your app.</p>
35
36<h2 id="network">Set Up a Network and Cache</h2>
37
38<p>A {@code RequestQueue} needs two things to do its job: a network to perform transport
39of the requests, and a cache to handle caching. There are standard implementations of these
40available in the Volley toolbox: {@code DiskBasedCache} provides a one-file-per-response
41cache with an in-memory index, and {@code BasicNetwork} provides a network transport based
42on your choice of {@link android.net.http.AndroidHttpClient} or {@link java.net.HttpURLConnection}.</p>
43
44<p>{@code BasicNetwork} is Volley's default network implementation. A {@code BasicNetwork}
45must be initialized with the HTTP client your app is using to connect to the network.
46Typically this is {@link android.net.http.AndroidHttpClient} or
47{@link java.net.HttpURLConnection}:</p>
48<ul>
49<li>Use {@link android.net.http.AndroidHttpClient} for apps targeting Android API levels
50lower than API Level 9 (Gingerbread). Prior to Gingerbread, {@link java.net.HttpURLConnection}
51was unreliable. For more discussion of this topic, see
52<a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">
53Android's HTTP Clients</a>. </li>
54
55<li>Use {@link java.net.HttpURLConnection} for apps targeting Android API Level 9
56(Gingerbread) and higher.</li>
57</ul>
58<p>To create an app that runs on all versions of Android, you can check the version of
59Android the device is running and choose the appropriate HTTP client, for example:</p>
60
61<pre>
62HttpStack stack;
63...
64// If the device is running a version >= Gingerbread...
65if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
66 // ...use HttpURLConnection for stack.
67} else {
68 // ...use AndroidHttpClient for stack.
69}
70Network network = new BasicNetwork(stack);
71</pre>
72
73<p>This snippet shows you the steps involved in setting up a
74{@code RequestQueue}:</p>
75
76<pre>
77RequestQueue mRequestQueue;
78
79// Instantiate the cache
80Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
81
82// Set up the network to use HttpURLConnection as the HTTP client.
83Network network = new BasicNetwork(new HurlStack());
84
85// Instantiate the RequestQueue with the cache and network.
86mRequestQueue = new RequestQueue(cache, network);
87
88// Start the queue
89mRequestQueue.start();
90
91String url ="http://www.myurl.com";
92
93// Formulate the request and handle the response.
94StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
95 new Response.Listener&lt;String&gt;() {
96 &#64;Override
97 public void onResponse(String response) {
98 // Do something with the response
99 }
100},
101 new Response.ErrorListener() {
102 &#64;Override
103 public void onErrorResponse(VolleyError error) {
104 // Handle error
105 }
106});
107
108// Add the request to the RequestQueue.
109mRequestQueue.add(stringRequest);
110...
111</pre>
112
113<p>If you just need to make a one-time request and don't want to leave the thread pool
114around, you can create the {@code RequestQueue} wherever you need it and call {@code stop()} on the
115{@code RequestQueue} once your response or error has come back, using the
116{@code Volley.newRequestQueue()} method described in <a href="simple.html">Sending a Simple
117Request</a>. But the more common use case is to create the {@code RequestQueue} as a
118singleton to keep it running for the lifetime of your app, as described in the next section.</p>
119
120
121<h2 id="singleton">Use a Singleton Pattern</h2>
122
123<p>If your application makes constant use of the network, it's probably most efficient to
124set up a single instance of {@code RequestQueue} that will last the lifetime of your app.
125You can achieve this in various ways. The recommended approach is to implement a singleton
126class that encapsulates {@code RequestQueue} and other Volley
127functionality. Another approach is to subclass {@link android.app.Application} and set up the
128{@code RequestQueue} in {@link android.app.Application#onCreate Application.onCreate()}.
129But this approach is <a href="{@docRoot}reference/android/app/Application.html">
130discouraged</a>; a static singleton can provide the same functionality in a more modular
131way. </p>
132
133<p>A key concept is that the {@code RequestQueue} must be instantiated with the
134{@link android.app.Application} context, not an {@link android.app.Activity} context. This
135ensures that the {@code RequestQueue} will last for the lifetime of your app, instead of
136being recreated every time the activity is recreated (for example, when the user
137rotates the device).
138
139<p>Here is an example of a singleton class that provides {@code RequestQueue} and
140{@code ImageLoader} functionality:</p>
141
142<pre>private static MySingleton mInstance;
143 private RequestQueue mRequestQueue;
144 private ImageLoader mImageLoader;
145 private static Context mCtx;
146
147 private MySingleton(Context context) {
148 mCtx = context;
149 mRequestQueue = getRequestQueue();
150
151 mImageLoader = new ImageLoader(mRequestQueue,
152 new ImageLoader.ImageCache() {
153 private final LruCache&lt;String, Bitmap&gt;
154 cache = new LruCache&lt;String, Bitmap&gt;(20);
155
156 &#64;Override
157 public Bitmap getBitmap(String url) {
158 return cache.get(url);
159 }
160
161 &#64;Override
162 public void putBitmap(String url, Bitmap bitmap) {
163 cache.put(url, bitmap);
164 }
165 });
166 }
167
168 public static synchronized MySingleton getInstance(Context context) {
169 if (mInstance == null) {
170 mInstance = new MySingleton(context);
171 }
172 return mInstance;
173 }
174
175 public RequestQueue getRequestQueue() {
176 if (mRequestQueue == null) {
177 // getApplicationContext() is key, it keeps you from leaking the
178 // Activity or BroadcastReceiver if someone passes one in.
179 mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
180 }
181 return mRequestQueue;
182 }
183
184 public &lt;T&gt; void addToRequestQueue(Request&lt;T&gt; req) {
185 getRequestQueue().add(req);
186 }
187
188 public ImageLoader getImageLoader() {
189 return mImageLoader;
190 }
191}</pre>
192
193<p>Here are some examples of performing {@code RequestQueue} operations using the singleton
194class:</p>
195
196<pre>
197// Get a RequestQueue
198RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()).
199 getRequestQueue();
200...
201
202// Add a request (in this example, called stringRequest) to your RequestQueue.
203MySingleton.getInstance(this).addToRequestQueue(stringRequest);
204</pre>