Volley框架的基本解讀(七)
阿新 • • 發佈:2019-02-07
在前面六篇部落格中,我們已經將Volley框架主線全部走完,今天我們來講講Volley框架中兩個十分重要的角色Request與Response,這兩個類之所以放到最後來講,一方面對Volley沒有一個清晰的認識,可能會比較難懂,另方面好戲不都是壓軸的嗎?
我們先看Request的原始碼:
public abstract class Request<T> implements Comparable<Request<T>>
它是一個抽象類,並實現了Comparable用於比較排序,還記得RequestQueue中的mCacheQueue與mNetworkQueue這兩個優先順序佇列嗎?實現Comparable介面就是為了能在佇列中排序,而從實現某些Request的優先請求。
我們還有先從構造方法開始看起:
public Request(String url, Response.ErrorListener listener) {
this(Method.DEPRECATED_GET_OR_POST, url, listener);
}
這個構造方法有兩個引數,分別是URL與錯誤回撥,它呼叫了另一個構造方法,Method是Request的一個內部介面,我們看看:
/** * Supported request methods. * 支援的請求方式 */ public interface Method { int DEPRECATED_GET_OR_POST = -1; int GET = 0; int POST = 1; int PUT = 2; int DELETE = 3; }
可見內部定義了四種支援的請求方式,DEPRECATED_GET_OR_POST這個大家可以無視,我也不是很理解,接著看:
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(); }
這裡為我們建立了一個重試策略並繫結在request中,mDefaultTrafficStatsTag是用於流量監控的唯一標識,通過URL產生。
Request內部定義了很多公共方法,比較重要的有這麼幾個,我們一起來看看:
/**
* Returns true if this request has been canceled.
*
* 是否取消該request
*/
public boolean isCanceled() {
return mCanceled;
}
/**
* Mark this request as canceled. No callback will be delivered.
* 取消請求
*/
public void cancel() {
mCanceled = true;
}
在之前的原始碼解析中我們經常可以看到isCanceled,現在我們知道它僅僅只是做了一個標識而已。
/**
* Returns the cache key for this request. By default, this is the URL.
* 獲取快取的Key,就是URL
*/
public String getCacheKey() {
return getUrl();
}
/**
* Returns the URL of this request.
* 請求URL
*/
public String getUrl() {
return mUrl;
}
getCacheKey該方法在快取解析的時候出現過,快取的Key就是URL。
/**
* Returns a Map of parameters to be used for a POST or PUT request. Can throw
* {@link AuthFailureError} as authentication may be required to provide these values.
*
* <p>Note that you can directly override {@link #getBody()} for custom data.</p>
*
* @throws AuthFailureError in the event of auth failure
*
* 空請求體,子類可以複寫該方法,如果子類需要的話
*/
protected Map<String, String> getParams() throws AuthFailureError {
return null;
}
public byte[] getBody() throws AuthFailureError {
Map<String, String> params = getParams();
if (params != null && params.size() > 0) {
return encodeParameters(params, getParamsEncoding());
}
return null;
}
private byte[] 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) {
throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
}
}
該方法用於POST請求,新增請求體。
/**
* Priority values. Requests will be processed from higher priorities to
* lower priorities, in FIFO order.
*
* 優先順序
*/
public enum Priority {
LOW,
NORMAL,
HIGH,
IMMEDIATE
}
/**
* Returns the {@link Priority} of this request; {@link Priority#NORMAL} by default.
*
* 獲取優先順序,預設正常
*/
public Priority getPriority() {
return Priority.NORMAL;
}
Request的優先順序,當你有急切請求需求的時候,就可以設定它。
/**
* Mark this request as having a response delivered on it. This can be used
* later in the request's lifetime for suppressing identical responses.
*
* 標記分發事件完畢
*/
public void markDelivered() {
mResponseDelivered = true;
}
它同樣是以個標記。
@Override
public int compareTo(Request<T> other) {
Priority left = this.getPriority();
Priority right = other.getPriority();
// High-priority requests are "lesser" so they are sorted to the front.
// Equal priorities are sorted by sequence number to provide FIFO ordering.
// 如果優先順序相等,按序列號排序,序列號高則放在後面
return left == right ?
this.mSequence - other.mSequence :
right.ordinal() - left.ordinal();
}
這裡是重點,request的比較,優先順序優先,如果優先順序相同,再比較序列號,序列號由RequestQueue中AtomicInteger類,我們呼叫add方法時生成並繫結在request中,AtomicInteger的incrementAndGet方法可以生成單調遞增的序列號。
/**
* Gets a sequence number.
*
* 生成單調遞增的序列號
*/
public int getSequenceNumber() {
return mSequenceGenerator.incrementAndGet();
}
Request有兩個抽象方法,
/**
* Subclasses must implement this to parse the raw network response
* and return an appropriate response type. This method will be
* called from a worker thread. The response will not be delivered
* if you return null.
* @param response Response from the network
* @return The parsed response, or null in the case of an error
*
* 解析response
*/
abstract protected Response<T> parseNetworkResponse(NetworkResponse response);
/**
* Subclasses must implement this to perform delivery of the parsed
* response to their listeners. The given response is guaranteed to
* be non-null; responses that fail to parse are not delivered.
* @param response The parsed response returned by
* {@link #parseNetworkResponse(NetworkResponse)}
*
* 分發Response
*/
abstract protected void deliverResponse(T response);
在說之前,我找個具體子類先看看,依然還是StringRequest:
@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);
}
一目瞭然,deliverResponse就是負責成功回撥,因為在request只定義了公共的錯誤回撥,成功回撥交由子類自己去實現,而parseNetworkResponse則負責解析NetworkResponse,每個不同的子類解析出不同的返回型別,如這裡的String,值得一提的是,這個方法之所以會定義在Request中是因為Request的泛型,只有Request知道它請求想讓Response返回的是什麼。