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}&mdash;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}&mdash;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}&mdash;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&lt;Bitmap&gt;() {
89        &#64;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>&lt;com.android.volley.toolbox.NetworkImageView
111        android:id=&quot;&#64;+id/networkImageView&quot;
112        android:layout_width=&quot;150dp&quot;
113        android:layout_height=&quot;170dp&quot;
114        android:layout_centerHorizontal=&quot;true&quot; /&gt;</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&lt;String, Bitmap&gt;
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    &#64;Override
196    protected int sizeOf(String key, Bitmap value) {
197        return value.getRowBytes() * value.getHeight();
198    }
199
200    &#64;Override
201    public Bitmap getBitmap(String url) {
202        return get(url);
203    }
204
205    &#64;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}&mdash;A request for retrieving a
240  {@link org.json.JSONArray}
241  response body at a given URL.</li>
242  <li>{@code JsonObjectRequest}&mdash;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&lt;JSONObject&gt;() {
261
262    &#64;Override
263    public void onResponse(JSONObject response) {
264        mTxtDisplay.setText("Response: " + response.toString());
265    }
266}, new Response.ErrorListener() {
267
268    &#64;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