Home | History | Annotate | Download | only in volley
      1 page.title=Implementing a Custom 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="#custom-request">Write a Custom Request</a></li>
     14 </ol>
     15 
     16 </div>
     17 </div>
     18 
     19 <a class="notice-developers-video wide" href="https://developers.google.com/events/io/sessions/325304728">
     20 <div>
     21     <h3>Video</h3>
     22     <p>Volley: Easy, Fast Networking for Android</p>
     23 </div>
     24 </a>
     25 
     26 <p>This lesson describes how to implement your own custom request types, for types that
     27 don't have out-of-the-box Volley support.</p>
     28 
     29 <h2 id="custom-request">Write a Custom Request</h2>
     30 
     31 Most requests have ready-to-use implementations in the toolbox; if your response is a string,
     32 image, or JSON, you probably won't need to implement a custom {@code Request}.</p>
     33 
     34 <p>For cases where you do need to implement a custom request, this is all you need
     35 to do:</p>
     36 
     37 <ul>
     38 
     39 <li>Extend the {@code Request&lt;T&gt;} class, where
     40 {@code &lt;T&gt;} represents the type of parsed response
     41 the request expects. So if your parsed response is a string, for example,
     42 create your custom request by extending {@code Request&lt;String&gt;}. See the Volley
     43 toolbox classes {@code StringRequest} and {@code ImageRequest} for examples of
     44 extending {@code Request&lt;T&gt;}.</li>
     45 
     46 <li>Implement the abstract methods {@code parseNetworkResponse()}
     47 and {@code deliverResponse()}, described in more detail below.</li>
     48 
     49 </ul>
     50 
     51 <h3>parseNetworkResponse</h3>
     52 
     53 <p>A {@code Response} encapsulates a parsed response for delivery, for a given type
     54 (such as string, image, or JSON). Here is a sample implementation of
     55 {@code parseNetworkResponse()}:</p>
     56 
     57 <pre>
     58 &#64;Override
     59 protected Response&lt;T&gt; parseNetworkResponse(
     60         NetworkResponse response) {
     61     try {
     62         String json = new String(response.data,
     63         HttpHeaderParser.parseCharset(response.headers));
     64     return Response.success(gson.fromJson(json, clazz),
     65     HttpHeaderParser.parseCacheHeaders(response));
     66     }
     67     // handle errors
     68 ...
     69 }
     70 </pre>
     71 
     72 <p>Note the following:</p>
     73 
     74 <ul>
     75 <li>{@code parseNetworkResponse()} takes as its parameter a {@code NetworkResponse}, which
     76 contains the response payload as a byte[], HTTP status code, and response headers.</li>
     77 <li>Your implementation must return a {@code Response&lt;T&gt;}, which contains your typed
     78 response object and cache metadata or an error, such as in the case of a parse failure.</li>
     79 </ul>
     80 
     81 <p>If your protocol has non-standard cache semantics, you can build a {@code Cache.Entry}
     82 yourself, but most requests are fine with something like this:
     83 </p>
     84 <pre>return Response.success(myDecodedObject,
     85         HttpHeaderParser.parseCacheHeaders(response));</pre>
     86 <p>
     87 Volley calls {@code parseNetworkResponse()} from a worker thread. This ensures that
     88 expensive parsing operations, such as decoding a JPEG into a Bitmap, don't block the UI
     89 thread.</p>
     90 
     91 <h3>deliverResponse</h3>
     92 
     93 <p>Volley calls you back on the main thread with the object you returned in
     94 {@code parseNetworkResponse()}. Most requests invoke a callback interface here,
     95 for example:
     96 </p>
     97 
     98 <pre>
     99 protected void deliverResponse(T response) {
    100         listener.onResponse(response);
    101 </pre>
    102 
    103 <h3>Example: GsonRequest</h3>
    104 
    105 <p><a href="http://code.google.com/p/google-gson/">Gson</a> is a library for converting
    106 Java objects to and from JSON using reflection. You can define Java objects that have the
    107 same names as their corresponding JSON keys, pass Gson the class object, and Gson will fill
    108 in the fields for you. Here's a complete implementation of a Volley request that uses
    109 Gson for parsing:</p>
    110 
    111 <pre>
    112 public class GsonRequest&lt;T&gt; extends Request&lt;T&gt; {
    113     private final Gson gson = new Gson();
    114     private final Class&lt;T&gt; clazz;
    115     private final Map&lt;String, String&gt; headers;
    116     private final Listener&lt;T&gt; listener;
    117 
    118     /**
    119      * Make a GET request and return a parsed object from JSON.
    120      *
    121      * &#64;param url URL of the request to make
    122      * &#64;param clazz Relevant class object, for Gson's reflection
    123      * &#64;param headers Map of request headers
    124      */
    125     public GsonRequest(String url, Class&lt;T&gt; clazz, Map&lt;String, String&gt; headers,
    126             Listener&lt;T&gt; listener, ErrorListener errorListener) {
    127         super(Method.GET, url, errorListener);
    128         this.clazz = clazz;
    129         this.headers = headers;
    130         this.listener = listener;
    131     }
    132 
    133     &#64;Override
    134     public Map&lt;String, String&gt; getHeaders() throws AuthFailureError {
    135         return headers != null ? headers : super.getHeaders();
    136     }
    137 
    138     &#64;Override
    139     protected void deliverResponse(T response) {
    140         listener.onResponse(response);
    141     }
    142 
    143     &#64;Override
    144     protected Response&lt;T&gt; parseNetworkResponse(NetworkResponse response) {
    145         try {
    146             String json = new String(
    147                     response.data,
    148                     HttpHeaderParser.parseCharset(response.headers));
    149             return Response.success(
    150                     gson.fromJson(json, clazz),
    151                     HttpHeaderParser.parseCacheHeaders(response));
    152         } catch (UnsupportedEncodingException e) {
    153             return Response.error(new ParseError(e));
    154         } catch (JsonSyntaxException e) {
    155             return Response.error(new ParseError(e));
    156         }
    157     }
    158 }
    159 </pre>
    160 
    161 <p>Volley provides ready-to-use {@code JsonArrayRequest} and {@code JsonArrayObject} classes
    162 if you prefer to take that approach. See <a href="request.html">
    163 Using Standard Request Types</a> for more information.</p>
    164