标签:
一、首先从每个POST或者GET请求的构造主体看起:XXXRequestpublic class StringRequest extends Request<String> { private final Listener<String> mListener; /** * 可以看到最终构造请求交由Request类去实现,HTTP的请求和响应均是由Request去处理 * * @param method the request {@link Method} to use;method在Request中给出了定义 * @param url URL to fetch the string at * @param listener Listener to receive the String response * @param errorListener Error listener, or null to ignore errors */ public StringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; } /** 默认为GET请求的构造函数*/ public StringRequest(String url, Listener<String> listener, ErrorListener errorListener) { this(Method.GET, url, listener, errorListener); } /** 这两个函数在父类Request均是abstract的*/ // 将服务器响应的数据进行回调 @Override protected void deliverResponse(String response) { mListener.onResponse(response); } // 对服务器响应发送的数据进行解析的函数,可以看到主体数据在NetworkResponse的data中 // 很明显返回的success函数中第一个函数即是解析后的数据 @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)); } }
public class JsonObjectRequest extends JsonRequest<JSONObject> public abstract class JsonRequest<T> extends Request<T>
public class JsonObjectRequest extends JsonRequest<JSONObject> { /** 可以看到JsonObjectRequest最终构造请求也交由Request类去实现 * 整个代码结构与StringRequest大同小异*/ public JsonObjectRequest(int method, String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener) { super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, errorListener); } public JsonObjectRequest(String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener) { this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest, listener, errorListener); } /*deliverResponse在父类JsonRequest中给予了实现*/ @Override protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) { try { String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); return Response.success(new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response)); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JSONException je) { return Response.error(new ParseError(je)); } } }2、查看JsonRequest
public abstract class JsonRequest<T> extends Request<T> { /** Request的编码格式. */ private static final String PROTOCOL_CHARSET = "utf-8"; /** Request的Content内容.*/ private static final String PROTOCOL_CONTENT_TYPE = String.format("application/json; charset=%s", PROTOCOL_CHARSET); private final Listener<T> mListener; private final String mRequestBody; /** * Deprecated constructor for a JsonRequest which defaults to GET unless {@link #getPostBody()} * or {@link #getPostParams()} is overridden (which defaults to POST). */ public JsonRequest(int method, String url, String requestBody, Listener<T> listener, ErrorListener errorListener) { super(method, url, errorListener);//这些均与StringRequest相类似,无非是多了mRequestBody mListener = listener; mRequestBody = requestBody; } @Override protected void deliverResponse(T response) { mListener.onResponse(response); } @Override abstract protected Response<T> parseNetworkResponse(NetworkResponse response); /** 这里重写了request中的相对应函数,来实现构造Request的具体内容 */ @Override public String getBodyContentType() { return PROTOCOL_CONTENT_TYPE; } @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; } } }
(三)有上面可以总结出,构造XXXRequest的一般实践方式,
1、构造真正的Request交由父类Requset<XXX>去实现-- super(method, url, errorListener);
2、定义自己的Listener,用以deliverResponse
3、重写parseNetworkResponse函数来解析服务器响应返回的数据
(四)根据上面的分析,来定义自己的XXXRequest,比如XMLRequest来获取XML类型的返回数据,这里copy了
(http://blog.csdn.net/guolin_blog/article/details/17612763)中的代码
public class XMLRequest extends Request<XmlPullParser> { /*********这里讲T替换成所需要解析成的数据类型***********/ 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 { /***************实现新的XMLRequset核心在于此,解析数据返回的数据,用以获取最终的解析结果*********************/ 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); } }其使用方式也与StringRequest大致相同,在Listener中可以添加对服务器response的数据的解析代码:
private RequestQueue mRequestQueue; mRequestQueue = Volley.newRequestQueue(this); String url = "http://flash.weather.com.cn/wmaps/xml/china.xml"; Response.Listener<XmlPullParser> listener = new Response.Listener<XmlPullParser>() { @Override public void onResponse(XmlPullParser response) { // 这里应该加上对于response的具体数据的解析 Log.d(TAG, response.toString()); } }; Response.ErrorListener errorListener = new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, error.getMessage()); } }; XMLRequest xmlRequest = new XMLRequest(url, listener, errorListener); mRequestQueue.add(xmlRequest);
(五)回过头来看Request的原码
1、先看一下其构造函数,也是前面几个XXXRequest调用的构造函数:
public Request(int method, String url, Response.ErrorListener listener) { mMethod = method; // 成员变量赋值 mUrl = url; mErrorListener = listener; setRetryPolicy(new DefaultRetryPolicy());// 设置重试策略 mDefaultTrafficStatsTag = TextUtils.isEmpty(url) ? 0: Uri.parse(url).getHost().hashCode(); }附I、重试策略
public class DefaultRetryPolicy implements RetryPolicy { .... /** The default socket timeout in milliseconds */ public static final int DEFAULT_TIMEOUT_MS = 2500;//默认socket超时时间 /** The default number of retries */ public static final int DEFAULT_MAX_RETRIES = 1; //默认重试次数 /** The default backoff multiplier */ public static final float DEFAULT_BACKOFF_MULT = 1f;//默认补偿系数 public DefaultRetryPolicy() { this(DEFAULT_TIMEOUT_MS, DEFAULT_MAX_RETRIES, DEFAULT_BACKOFF_MULT); } .... }而setRetryPolicy即是一个简单的setter函数:
/** The retry policy for this request. */ private RetryPolicy mRetryPolicy; public void setRetryPolicy(RetryPolicy retryPolicy) { mRetryPolicy = retryPolicy; }2、剩下的便是一连串的setter与getter函数,前面还用到的函数有:
abstract protected Response<T> parseNetworkResponse(NetworkResponse response); abstract protected void deliverResponse(T response);
private static final String DEFAULT_PARAMS_ENCODING = "UTF-8"; protected Map<String, String> getParams() throws AuthFailureError { return null; } protected String getParamsEncoding() { return DEFAULT_PARAMS_ENCODING; } public String getBodyContentType() { return "application/x-www-form-urlencoded; charset=" + getParamsEncoding(); } /** * Returns the raw POST or PUT body to be sent. */ public byte[] getBody() throws AuthFailureError { Map<String, String> params = getParams();// 由上面getParams方法的定义可以看出,要使用本方法, // 应该重载getParams方法,或者直接重载getBody() if (params != null && params.size() > 0) { return encodeParameters(params, getParamsEncoding()); } returnnull; } /** * Converts <code>params</code> into an application/x-www-form-urlencoded encoded string. */ privatebyte[] encodeParameters(Map<String, String> params, String paramsEncoding) { StringBuilder encodedParams = new StringBuilder(); try { for (Map.Entry<String, String> entry : params.entrySet()) { encodedParams.append(URLEncoder.encode(entry.getKey(), paramsEncoding)); encodedParams.append('='); encodedParams.append(URLEncoder.encode(entry.getValue(), paramsEncoding)); encodedParams.append('&'); } return encodedParams.toString().getBytes(paramsEncoding); } catch (UnsupportedEncodingException uee) { thrownew RuntimeException("Encoding not supported: " + paramsEncoding, uee); } }
标签:
原文地址:http://blog.csdn.net/woliuyunyicai/article/details/46535261