詳細解讀Volley(四)—— 自定義Request

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;
    }

}
View Code

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;
    }

}
View Code

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;  
        }  
    }  
}  
View Code

測試代碼:

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

相關文章
相關標籤/搜索