Volley中提供了幾個Request,若是咱們有特殊的需求,徹底能夠自定義Request的,自定義Request天然要繼承Request,那麼本篇就教你們來一步一步地定義一個本身的Request類。html
1、繼承Requestnode
若是咱們的request的對象不是string,也不是JsonObject,而是一個奇怪的對象呢?我這裏創建了一個類,叫作:Kale,而後定義了一個CustomReqeust去繼承Reqeust,獲得以下的代碼。android
package com.kale.volleytest; import com.android.volley.NetworkResponse; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.Response.ErrorListener; import com.android.volley.Response.Listener; public class CustomReqeust extends Request<Kale>{ public CustomReqeust(int method, String url, ErrorListener listener) { super(method, url, listener); } @Override protected Response<Kale> parseNetworkResponse(NetworkResponse response) { // TODO 自動生成的方法存根 return null; } @Override protected void deliverResponse(Kale response) { // TODO 自動生成的方法存根 } }
分析:json
public CustomReqeust(int method, String url, ErrorListener listener)
數組
構造函數中調用了父類的方法,初始化了當前對象。傳入三個參數:①請求方式,即POST/GET,②請求的URL,③出錯時的回調監聽器服務器
protected Response<Kale> parseNetworkResponse(NetworkResponse response)網絡
解析網絡響應的結果,從NetworkResponse的代碼中咱們就能夠知道它裏面有什麼東西了。ide
/** * Data and headers returned from {@link Network#performRequest(Request)}. */ public class NetworkResponse { /** * Creates a new network response. * @param statusCode the HTTP status code * @param data Response body * @param headers Headers returned with this response, or null for none * @param notModified True if the server returned a 304 and the data was already in cache * @param networkTimeMs Round-trip network time to receive network response */ public NetworkResponse(int statusCode, byte[] data, Map<String, String> headers, boolean notModified, long networkTimeMs)
響應碼啊,請求頭什麼的,最最主要的就是這個比特數組的data,響應的結果就在裏面。咱們能夠自由的進行處理了~函數
protected void deliverResponse(Kale response)post
分發響應的結果,咱們能夠經過將這個response放到監聽器裏來獲取響應結果。
2、分析StringRequest
咱們如今已經對request的子類有了基本的認識,如今就來看看StringRequest的源碼吧,別擔憂,很短!
package com.android.volley.toolbox;public class StringRequest extends Request<String> { // 創建監聽器來得到響應成功時返回的結果 private final Listener<String> mListener; // 傳入請求方法,url,成功時的監聽器,失敗時的監聽器 public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); // 初始化成功時的監聽器 mListener = listener; } /** * Creates a new GET request. * 創建一個默認的GET請求,調用了上面的構造函數 */ public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) { this(Method.GET, url, listener, errorListener); } @Override protected void deliverResponse(String response) { // 用監聽器的方法來傳遞下響應的結果 mListener.onResponse(response); } @Override protected Response<String> parseNetworkResponse(NetworkResponse response) { String parsed; try { // 調用了new String(byte[] data, String charsetName) 這個構造函數來構建String對象, // 將byte數組按照特定的編碼方式轉換爲String對象 // 主要部分是data parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); } }
分析完代碼咱們應該就能知道改如何自定義Request了,其實沒啥高深的東西。
3、自定義XMLRequest
代碼來自:http://blog.csdn.net/guolin_blog/article/details/17612763
public class XMLRequest extends Request<XmlPullParser> { private final Listener<XmlPullParser> mListener; public XMLRequest(int method, String url, Listener<XmlPullParser> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; } public XMLRequest(String url, Listener<XmlPullParser> listener, ErrorListener errorListener) { this(Method.GET, url, listener, errorListener); } @Override protected Response<XmlPullParser> parseNetworkResponse(NetworkResponse response) { try { String xmlString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser = factory.newPullParser(); xmlPullParser.setInput(new StringReader(xmlString)); return Response.success(xmlPullParser, HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (XmlPullParserException e) { return Response.error(new ParseError(e)); } } @Override protected void deliverResponse(XmlPullParser response) { mListener.onResponse(response); } }
這裏用到了XmlPull的知識,若是不是很瞭解,能夠去這篇文章看看:http://www.cnblogs.com/tianzhijiexian/p/4020250.html
測試代碼:
XMLRequest xmlRequest = new XMLRequest( "http://flash.weather.com.cn/wmaps/xml/china.xml", new Response.Listener<XmlPullParser>() { @Override public void onResponse(XmlPullParser response) { try { int eventType = response.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_TAG: String nodeName = response.getName(); if ("city".equals(nodeName)) { String pName = response.getAttributeValue(0); Log.d("TAG", "pName is " + pName); } break; } eventType = response.next(); } } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("TAG", error.getMessage(), error); } }); mQueue.add(xmlRequest);
結果:
4、自定義GsonRequest
代碼來自:http://blog.csdn.net/guolin_blog/article/details/17612763
public class GsonRequest<T> extends Request<T> { private final Listener<T> mListener; private Gson mGson; private Class<T> mClass; public GsonRequest(int method, String url, Class<T> clazz, Listener<T> listener, ErrorListener errorListener) { super(method, url, errorListener); mGson = new Gson(); mClass = clazz; mListener = listener; } public GsonRequest(String url, Class<T> clazz, Listener<T> listener, ErrorListener errorListener) { this(Method.GET, url, clazz, listener, errorListener); } @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { try { String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); return Response.success(mGson.fromJson(jsonString, mClass), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } } @Override protected void deliverResponse(T response) { mListener.onResponse(response); } }
代碼十分簡單,先是將服務器響應的數據解析出來,而後經過調用Gson的fromJson方法將數據組裝成對象。在deliverResponse方法中仍然是將最終的數據進行回調。
用法:
創建一個對象類,好比這裏的weather、WeatherInfo類,而後初始化GsonRequest對象,最後把GsonRequest對象添加到隊列中。
Weather:
public class Weather { private WeatherInfo weatherinfo; public WeatherInfo getWeatherinfo() { return weatherinfo; } public void setWeatherinfo(WeatherInfo weatherinfo) { this.weatherinfo = weatherinfo; } }
WeatherInfo:
public class WeatherInfo { private String city; private String temp; private String time; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getTemp() { return temp; } public void setTemp(String temp) { this.temp = temp; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } }
Java測試代碼:
GsonRequest<Weather> gsonRequest = new GsonRequest<Weather>( "http://www.weather.com.cn/data/sk/101010100.html", Weather.class, new Response.Listener<Weather>() { @Override public void onResponse(Weather weather) { WeatherInfo weatherInfo = weather.getWeatherinfo(); Log.d("TAG", "city is " + weatherInfo.getCity()); Log.d("TAG", "temp is " + weatherInfo.getTemp()); Log.d("TAG", "time is " + weatherInfo.getTime()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("TAG", error.getMessage(), error); } }); mQueue.add(gsonRequest);
5、重寫getBody()方法來添加post參數
咱們能夠在JsonRequest類中發現以下代碼:
/** * Returns the raw POST or PUT body to be sent. * * @throws AuthFailureError in the event of auth failure */ @Override public byte[] getBody() { try { return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET); } catch (UnsupportedEncodingException uee) { VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mRequestBody, PROTOCOL_CHARSET); return null; } }
不用看代碼,直接看註釋,說明這裏執行post請求,因此咱們能夠在這裏設置post參數。這裏
return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);
返回的就是post參數了。
若是咱們想要傳遞POST數據,能夠參考上面的代碼,重寫Request的getBody()方法,放入本身的參數,舉例以下:
/** http請求編碼方式 */ private static final String PROTOCOL_CHARSET = "utf-8"; private String mUserName;
@Override public byte[] getBody() { try { return mUserName == null ? null : mUserName.getBytes(PROTOCOL_CHARSET); } catch (UnsupportedEncodingException uee) { VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mUserName, PROTOCOL_CHARSET); return null; } }
完整代碼(來自:http://blog.csdn.net/ttdevs/article/details/17586205):
public class CustomReqeust extends Request<String> { /** http請求編碼方式 */ private static final String PROTOCOL_CHARSET = "utf-8"; private Listener<String> mListener; private String mUserName; public CustomReqeust(String url, String userName, Listener<String> listener, ErrorListener errorListener) { super(Method.POST, url, errorListener); mUserName = userName; mListener = listener; } @Override protected Response<String> parseNetworkResponse(NetworkResponse response) { String parsed; try { parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); } @Override protected void deliverResponse(String response) { mListener.onResponse(response); } @Override public byte[] getBody() { try { return mUserName == null ? null : mUserName.getBytes(PROTOCOL_CHARSET); } catch (UnsupportedEncodingException uee) { VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mUserName, PROTOCOL_CHARSET); return null; } } }
測試代碼:
private void customRequest() { CustomReqeust request = new CustomReqeust(URL, "CustomVolley", new Listener<String>() { @Override public void onResponse(String arg0) { Toast.makeText(getApplicationContext(), arg0, Toast.LENGTH_LONG).show(); Log.d("onResponse", arg0); } }, new ErrorListener() { @Override public void onErrorResponse(VolleyError arg0) { Toast.makeText(getApplicationContext(), arg0.toString(), Toast.LENGTH_LONG).show(); Log.d("onErrorResponse", arg0.toString()); } }); mQueue.add(request); }
抓包結果:
獲得了傳遞的username = CustomVolley
參考自:
http://blog.csdn.net/t12x3456/article/details/9221611
http://blog.csdn.net/guolin_blog/article/details/17612763
http://blog.csdn.net/ttdevs/article/details/17586205