1 page.title=Making a Standard Request 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="#request-image">Request an Image</a></li> 14 <li><a href="#request-json">Request JSON</a></li> 15 </ol> 16 17 </div> 18 </div> 19 20 <a class="notice-developers-video wide" href="https://www.youtube.com/watch?v=yhv8l9F44qo"> 21 <div> 22 <h3>Video</h3> 23 <p>Volley: Easy, Fast Networking for Android</p> 24 </div> 25 </a> 26 27 <p> 28 This lesson describes how to use the common request types that Volley supports:</p> 29 30 <ul> 31 <li>{@code StringRequest}. Specify a URL and receive a raw string in response. See 32 <a href="requestqueue.html">Setting Up a Request Queue</a> for an example.</li> 33 <li>{@code ImageRequest}. Specify a URL and receive an image in response.</li> 34 <li>{@code JsonObjectRequest} and {@code JsonArrayRequest} (both subclasses of 35 {@code JsonRequest}). Specify a URL and get a JSON object or array (respectively) in 36 response.</li> 37 </ul> 38 39 <p>If your expected response is one of these types, you probably won't have to implement a 40 custom request. This lesson describes how to use these standard request types. For 41 information on how to implement your own custom request, see <a href="request-custom.html"> 42 Implementing a Custom Request</a>.</p> 43 44 45 <h2 id="request-image">Request an Image</h2> 46 47 <p>Volley offers the following classes for requesting images. These classes layer on top 48 of each other to offer different levels of support for processing images:</p> 49 50 <ul> 51 <li>{@code ImageRequest}—a canned request for getting an image at a given URL and 52 calling back with a decoded bitmap. It also provides convenience features like specifying 53 a size to resize to. Its main benefit is that Volley's thread scheduling ensures that 54 expensive image operations (decoding, resizing) automatically happen on a worker thread.</li> 55 56 <li>{@code ImageLoader}—a helper class that handles loading and caching images from 57 remote URLs. {@code ImageLoader} is a an orchestrator for large numbers of {@code ImageRequest}s, 58 for example when putting multiple thumbnails in a {@link android.widget.ListView}. 59 {@code ImageLoader} provides an in-memory cache to sit in front of the normal Volley 60 cache, which is important to prevent flickering. This makes it possible to achieve a 61 cache hit without blocking or deferring off the main thread, which is impossible when 62 using disk I/O. {@code ImageLoader} also does response coalescing, without which almost 63 every response handler would set a bitmap on a view and cause a layout pass per image. 64 Coalescing makes it possible to deliver multiple responses simultaneously, which improves 65 performance.</li> 66 <li>{@code NetworkImageView}—builds on {@code ImageLoader} and effectively replaces 67 {@link android.widget.ImageView} for situations where your image is being fetched over 68 the network via URL. {@code NetworkImageView} also manages canceling pending requests if 69 the view is detached from the hierarchy.</li> 70 </ul> 71 72 <h3>Use ImageRequest</h3> 73 74 <p>Here is an example of using {@code ImageRequest}. It retrieves the image specified by 75 the URL and displays it in the app. Note that this snippet interacts with the 76 {@code RequestQueue} through a singleton class (see <a href="{@docRoot} 77 training/volley/requestqueue.html#singleton">Setting Up a RequestQueue</a> for more discussion of 78 this topic):</p> 79 80 <pre> 81 ImageView mImageView; 82 String url = "http://i.imgur.com/7spzG.png"; 83 mImageView = (ImageView) findViewById(R.id.myImage); 84 ... 85 86 // Retrieves an image specified by the URL, displays it in the UI. 87 ImageRequest request = new ImageRequest(url, 88 new Response.Listener<Bitmap>() { 89 @Override 90 public void onResponse(Bitmap bitmap) { 91 mImageView.setImageBitmap(bitmap); 92 } 93 }, 0, 0, null, 94 new Response.ErrorListener() { 95 public void onErrorResponse(VolleyError error) { 96 mImageView.setImageResource(R.drawable.image_load_error); 97 } 98 }); 99 // Access the RequestQueue through your singleton class. 100 MySingleton.getInstance(this).addToRequestQueue(request);</pre> 101 102 103 <h3>Use ImageLoader and NetworkImageView</h3> 104 105 <p>You can use {@code ImageLoader} and {@code NetworkImageView} in concert to efficiently 106 manage the display of multiple images, such as in a {@link android.widget.ListView}. In your 107 layout XML file, you use {@code NetworkImageView} in much the same way you would use 108 {@link android.widget.ImageView}, for example:</p> 109 110 <pre><com.android.volley.toolbox.NetworkImageView 111 android:id="@+id/networkImageView" 112 android:layout_width="150dp" 113 android:layout_height="170dp" 114 android:layout_centerHorizontal="true" /></pre> 115 116 <p>You can use {@code ImageLoader} by itself to display an image, for example:</p> 117 118 <pre> 119 ImageLoader mImageLoader; 120 ImageView mImageView; 121 // The URL for the image that is being loaded. 122 private static final String IMAGE_URL = 123 "http://developer.android.com/images/training/system-ui.png"; 124 ... 125 mImageView = (ImageView) findViewById(R.id.regularImageView); 126 127 // Get the ImageLoader through your singleton class. 128 mImageLoader = MySingleton.getInstance(this).getImageLoader(); 129 mImageLoader.get(IMAGE_URL, ImageLoader.getImageListener(mImageView, 130 R.drawable.def_image, R.drawable.err_image)); 131 </pre> 132 133 <p>However, {@code NetworkImageView} can do this for you if all you're doing is populating 134 an {@link android.widget.ImageView}. For example:</p> 135 136 <pre> 137 ImageLoader mImageLoader; 138 NetworkImageView mNetworkImageView; 139 private static final String IMAGE_URL = 140 "http://developer.android.com/images/training/system-ui.png"; 141 ... 142 143 // Get the NetworkImageView that will display the image. 144 mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView); 145 146 // Get the ImageLoader through your singleton class. 147 mImageLoader = MySingleton.getInstance(this).getImageLoader(); 148 149 // Set the URL of the image that should be loaded into this view, and 150 // specify the ImageLoader that will be used to make the request. 151 mNetworkImageView.setImageUrl(IMAGE_URL, mImageLoader); 152 </pre> 153 154 <p>The above snippets access the {@code RequestQueue} and the {@code ImageLoader} 155 through a singleton class, as described in <a href="{@docRoot}training/volley/requestqueue.html#singleton"> 156 Setting Up a RequestQueue</a>. This approach ensures that your app creates single instances of 157 these classes that last the lifetime of your app. The reason that this is important for 158 {@code ImageLoader} (the helper class that handles loading and caching images) is that 159 the main function of the in-memory cache is to allow for flickerless rotation. Using a 160 singleton pattern allows the bitmap cache to outlive the activity. If instead you create the 161 {@code ImageLoader} in an activity, the {@code ImageLoader} would be recreated along with 162 the activity every time the user rotates the device. This would cause flickering.</p> 163 164 <h4 id="lru-cache">Example LRU cache</h4> 165 166 <p>The Volley toolbox provides a standard cache implementation via the 167 {@code DiskBasedCache} class. This class caches files directly onto the hard disk in the 168 specified directory. But to use {@code ImageLoader}, you should provide a custom 169 in-memory LRU bitmap cache that implements the {@code ImageLoader.ImageCache} interface. 170 You may want to set up your cache as a singleton; for more discussion of this topic, see 171 <a href="{@docRoot}training/volley/requestqueue.html#singleton"> 172 Setting Up a RequestQueue</a>.</p> 173 174 <p>Here is a sample implementation for an in-memory {@code LruBitmapCache} class. 175 It extends the {@link android.support.v4.util.LruCache} class and implements the 176 {@code ImageLoader.ImageCache} interface:</p> 177 178 <pre> 179 import android.graphics.Bitmap; 180 import android.support.v4.util.LruCache; 181 import android.util.DisplayMetrics; 182 import com.android.volley.toolbox.ImageLoader.ImageCache; 183 184 public class LruBitmapCache extends LruCache<String, Bitmap> 185 implements ImageCache { 186 187 public LruBitmapCache(int maxSize) { 188 super(maxSize); 189 } 190 191 public LruBitmapCache(Context ctx) { 192 this(getCacheSize(ctx)); 193 } 194 195 @Override 196 protected int sizeOf(String key, Bitmap value) { 197 return value.getRowBytes() * value.getHeight(); 198 } 199 200 @Override 201 public Bitmap getBitmap(String url) { 202 return get(url); 203 } 204 205 @Override 206 public void putBitmap(String url, Bitmap bitmap) { 207 put(url, bitmap); 208 } 209 210 // Returns a cache size equal to approximately three screens worth of images. 211 public static int getCacheSize(Context ctx) { 212 final DisplayMetrics displayMetrics = ctx.getResources(). 213 getDisplayMetrics(); 214 final int screenWidth = displayMetrics.widthPixels; 215 final int screenHeight = displayMetrics.heightPixels; 216 // 4 bytes per pixel 217 final int screenBytes = screenWidth * screenHeight * 4; 218 219 return screenBytes * 3; 220 } 221 } 222 </pre> 223 224 <p>Here is an example of how to instantiate an {@code ImageLoader} to use this 225 cache:</p> 226 227 <pre> 228 RequestQueue mRequestQueue; // assume this exists. 229 ImageLoader mImageLoader = new ImageLoader(mRequestQueue, new LruBitmapCache( 230 LruBitmapCache.getCacheSize())); 231 </pre> 232 233 234 <h2 id="request-json">Request JSON</h2> 235 236 <p>Volley provides the following classes for JSON requests:</p> 237 238 <ul> 239 <li>{@code JsonArrayRequest}—A request for retrieving a 240 {@link org.json.JSONArray} 241 response body at a given URL.</li> 242 <li>{@code JsonObjectRequest}—A request for retrieving a 243 {@link org.json.JSONObject} 244 response body at a given URL, allowing for an optional 245 {@link org.json.JSONObject} 246 to be passed in as part of the request body.</li> 247 </ul> 248 249 <p>Both classes are based on the common base class {@code JsonRequest}. You use them 250 following the same basic pattern you use for other types of requests. For example, this 251 snippet fetches a JSON feed and displays it as text in the UI:</p> 252 253 <pre> 254 TextView mTxtDisplay; 255 ImageView mImageView; 256 mTxtDisplay = (TextView) findViewById(R.id.txtDisplay); 257 String url = "http://my-json-feed"; 258 259 JsonObjectRequest jsObjRequest = new JsonObjectRequest 260 (Request.Method.GET, url, null, new Response.Listener<JSONObject>() { 261 262 @Override 263 public void onResponse(JSONObject response) { 264 mTxtDisplay.setText("Response: " + response.toString()); 265 } 266 }, new Response.ErrorListener() { 267 268 @Override 269 public void onErrorResponse(VolleyError error) { 270 // TODO Auto-generated method stub 271 272 } 273 }); 274 275 // Access the RequestQueue through your singleton class. 276 MySingleton.getInstance(this).addToRequestQueue(jsObjRequest); 277 </pre> 278 279 For an example of implementing a custom JSON request based on 280 <a href="http://code.google.com/p/google-gson/">Gson</a>, see the next lesson, 281 <a href="request-custom.html">Implementing a Custom Request</a>. 282