1. 程式人生 > >Volley框架的基本解讀(七)

Volley框架的基本解讀(七)

在前面六篇部落格中,我們已經將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返回的是什麼。