1page.title=Implementing a Custom 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="#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 27don't have out-of-the-box Volley support.</p> 28 29<h2 id="custom-request">Write a Custom Request</h2> 30 31Most requests have ready-to-use implementations in the toolbox; if your response is a string, 32image, 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 35to do:</p> 36 37<ul> 38 39<li>Extend the {@code Request<T>} class, where 40{@code <T>} represents the type of parsed response 41the request expects. So if your parsed response is a string, for example, 42create your custom request by extending {@code Request<String>}. See the Volley 43toolbox classes {@code StringRequest} and {@code ImageRequest} for examples of 44extending {@code Request<T>}.</li> 45 46<li>Implement the abstract methods {@code parseNetworkResponse()} 47and {@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@Override 59protected Response<T> 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 76contains the response payload as a byte[], HTTP status code, and response headers.</li> 77<li>Your implementation must return a {@code Response<T>}, which contains your typed 78response 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} 82yourself, but most requests are fine with something like this: 83</p> 84<pre>return Response.success(myDecodedObject, 85 HttpHeaderParser.parseCacheHeaders(response));</pre> 86<p> 87Volley calls {@code parseNetworkResponse()} from a worker thread. This ensures that 88expensive parsing operations, such as decoding a JPEG into a Bitmap, don't block the UI 89thread.</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, 95for example: 96</p> 97 98<pre> 99protected 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 106Java objects to and from JSON using reflection. You can define Java objects that have the 107same names as their corresponding JSON keys, pass Gson the class object, and Gson will fill 108in the fields for you. Here's a complete implementation of a Volley request that uses 109Gson for parsing:</p> 110 111<pre> 112public class GsonRequest<T> extends Request<T> { 113 private final Gson gson = new Gson(); 114 private final Class<T> clazz; 115 private final Map<String, String> headers; 116 private final Listener<T> listener; 117 118 /** 119 * Make a GET request and return a parsed object from JSON. 120 * 121 * @param url URL of the request to make 122 * @param clazz Relevant class object, for Gson's reflection 123 * @param headers Map of request headers 124 */ 125 public GsonRequest(String url, Class<T> clazz, Map<String, String> headers, 126 Listener<T> listener, ErrorListener errorListener) { 127 super(Method.GET, url, errorListener); 128 this.clazz = clazz; 129 this.headers = headers; 130 this.listener = listener; 131 } 132 133 @Override 134 public Map<String, String> getHeaders() throws AuthFailureError { 135 return headers != null ? headers : super.getHeaders(); 136 } 137 138 @Override 139 protected void deliverResponse(T response) { 140 listener.onResponse(response); 141 } 142 143 @Override 144 protected Response<T> 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 162if you prefer to take that approach. See <a href="request.html"> 163Using Standard Request Types</a> for more information.</p> 164