1 page.title=Setting Up a RequestQueue 2 3 trainingnavtop=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 30 Volley'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} 34 as 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 39 of the requests, and a cache to handle caching. There are standard implementations of these 40 available in the Volley toolbox: {@code DiskBasedCache} provides a one-file-per-response 41 cache with an in-memory index, and {@code BasicNetwork} provides a network transport based 42 on 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} 45 must be initialized with the HTTP client your app is using to connect to the network. 46 Typically 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 50 lower than API Level 9 (Gingerbread). Prior to Gingerbread, {@link java.net.HttpURLConnection} 51 was unreliable. For more discussion of this topic, see 52 <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html"> 53 Android'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 59 Android the device is running and choose the appropriate HTTP client, for example:</p> 60 61 <pre> 62 HttpStack stack; 63 ... 64 // If the device is running a version >= Gingerbread... 65 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { 66 // ...use HttpURLConnection for stack. 67 } else { 68 // ...use AndroidHttpClient for stack. 69 } 70 Network 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> 77 RequestQueue mRequestQueue; 78 79 // Instantiate the cache 80 Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap 81 82 // Set up the network to use HttpURLConnection as the HTTP client. 83 Network network = new BasicNetwork(new HurlStack()); 84 85 // Instantiate the RequestQueue with the cache and network. 86 mRequestQueue = new RequestQueue(cache, network); 87 88 // Start the queue 89 mRequestQueue.start(); 90 91 String url ="http://www.myurl.com"; 92 93 // Formulate the request and handle the response. 94 StringRequest stringRequest = new StringRequest(Request.Method.GET, url, 95 new Response.Listener<String>() { 96 @Override 97 public void onResponse(String response) { 98 // Do something with the response 99 } 100 }, 101 new Response.ErrorListener() { 102 @Override 103 public void onErrorResponse(VolleyError error) { 104 // Handle error 105 } 106 }); 107 108 // Add the request to the RequestQueue. 109 mRequestQueue.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 114 around, 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 117 Request</a>. But the more common use case is to create the {@code RequestQueue} as a 118 singleton 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 124 set up a single instance of {@code RequestQueue} that will last the lifetime of your app. 125 You can achieve this in various ways. The recommended approach is to implement a singleton 126 class that encapsulates {@code RequestQueue} and other Volley 127 functionality. Another approach is to subclass {@link android.app.Application} and set up the 128 {@code RequestQueue} in {@link android.app.Application#onCreate Application.onCreate()}. 129 But this approach is <a href="{@docRoot}reference/android/app/Application.html"> 130 discouraged</a>; a static singleton can provide the same functionality in a more modular 131 way. </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 135 ensures that the {@code RequestQueue} will last for the lifetime of your app, instead of 136 being recreated every time the activity is recreated (for example, when the user 137 rotates 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<String, Bitmap> 154 cache = new LruCache<String, Bitmap>(20); 155 156 @Override 157 public Bitmap getBitmap(String url) { 158 return cache.get(url); 159 } 160 161 @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 <T> void addToRequestQueue(Request<T> 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 194 class:</p> 195 196 <pre> 197 // Get a RequestQueue 198 RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()). 199 getRequestQueue(); 200 ... 201 202 // Add a request (in this example, called stringRequest) to your RequestQueue. 203 MySingleton.getInstance(this).addToRequestQueue(stringRequest); 204 </pre> 205