1page.title=Making a Standard Request 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="#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://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<p> 28This 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 40custom request. This lesson describes how to use these standard request types. For 41information on how to implement your own custom request, see <a href="requests-custom.html"> 42Implementing 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 48of 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 75the 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} 77training/volley/requestqueue.html#singleton">Setting Up a RequestQueue</a> for more discussion of 78this topic):</p> 79 80<pre> 81ImageView mImageView; 82String url = "http://i.imgur.com/7spzG.png"; 83mImageView = (ImageView) findViewById(R.id.myImage); 84... 85 86// Retrieves an image specified by the URL, displays it in the UI. 87ImageRequest 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. 100MySingleton.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 106manage the display of multiple images, such as in a {@link android.widget.ListView}. In your 107layout 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> 119ImageLoader mImageLoader; 120ImageView mImageView; 121// The URL for the image that is being loaded. 122private static final String IMAGE_URL = 123 "http://developer.android.com/images/training/system-ui.png"; 124... 125mImageView = (ImageView) findViewById(R.id.regularImageView); 126 127// Get the ImageLoader through your singleton class. 128mImageLoader = MySingleton.getInstance(this).getImageLoader(); 129mImageLoader.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 134an {@link android.widget.ImageView}. For example:</p> 135 136<pre> 137ImageLoader mImageLoader; 138NetworkImageView mNetworkImageView; 139private 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. 144mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView); 145 146// Get the ImageLoader through your singleton class. 147mImageLoader = 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. 151mNetworkImageView.setImageUrl(IMAGE_URL, mImageLoader); 152</pre> 153 154<p>The above snippets access the {@code RequestQueue} and the {@code ImageLoader} 155through a singleton class, as described in <a href="{@docRoot}training/volley/requestqueue.html#singleton"> 156Setting Up a RequestQueue</a>. This approach ensures that your app creates single instances of 157these 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 159the main function of the in-memory cache is to allow for flickerless rotation. Using a 160singleton 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 162the 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 168specified directory. But to use {@code ImageLoader}, you should provide a custom 169in-memory LRU bitmap cache that implements the {@code ImageLoader.ImageCache} interface. 170You 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"> 172Setting Up a RequestQueue</a>.</p> 173 174<p>Here is a sample implementation for an in-memory {@code LruBitmapCache} class. 175It extends the {@link android.support.v4.util.LruCache} class and implements the 176{@code ImageLoader.ImageCache} interface:</p> 177 178<pre> 179import android.graphics.Bitmap; 180import android.support.v4.util.LruCache; 181import android.util.DisplayMetrics; 182import com.android.volley.toolbox.ImageLoader.ImageCache; 183 184public 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 225cache:</p> 226 227<pre> 228RequestQueue mRequestQueue; // assume this exists. 229ImageLoader 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 250following the same basic pattern you use for other types of requests. For example, this 251snippet fetches a JSON feed and displays it as text in the UI:</p> 252 253<pre> 254TextView mTxtDisplay; 255ImageView mImageView; 256mTxtDisplay = (TextView) findViewById(R.id.txtDisplay); 257String url = "http://my-json-feed"; 258 259JsonObjectRequest 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. 276MySingleton.getInstance(this).addToRequestQueue(jsObjRequest); 277</pre> 278 279For 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