Volley框架的基本解读

Posted zero-27

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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返回的是什么。


以上是关于Volley框架的基本解读的主要内容,如果未能解决你的问题,请参考以下文章

Volley框架的基本解读

Volley框架的基本解读

Volley框架的基本解读

Volley框架的基本解读

Volley框架的基本解读

Volley源码解读(上)