| Katie McCormick | 1a89ae4 | 2014-03-18 17:13:50 -0700 | [diff] [blame] | 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> |