Volley源码分析(二)- Request

上一篇Volley源码分析(一)- 初始化说到初始化后返回了RequestQueue实例。然后通过add方法添加Request。再详细分析add方法前,我们先来看下Request这个类。

/**
 * Base class for all network requests.
 *
 * @param  The type of parsed response this request expects.
 */
public abstract class Request implements Comparable> 

所有网络请求的基类,Volley默认实现了以下派生类:ImageRequest、ClearCacheRequest、StringRequest、JsonRequest。JsonRequest又派生出来JsonObjectRequest、JsonArrayRequest。所有派生类都必须实现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
     */
    abstract protected Response parseNetworkResponse(NetworkResponse response);

由于这些内容都很简单,都是一些基础知识,这里就不扩展讲更多,具体的可以看我代码中的GsonRequest类。这里说明下,这个方法是子线程执行的,所以可以把Json解析的放在这里做。

下面就从add方法继续分析。

     /**
     * Adds a Request to the dispatch queue.
     * @param request The request to service
     * @return The passed-in request
     */
    public  Request add(Request request) {
        // Tag the request as belonging to this queue and add it to the set of current requests.
        request.setRequestQueue(this);
        synchronized (mCurrentRequests) {
            mCurrentRequests.add(request);
        }

        // Process requests in the order they are added.
        request.setSequence(getSequenceNumber());
        request.addMarker("add-to-queue");

        // If the request is uncacheable, skip the cache queue and go straight to the network.
        if (!request.shouldCache()) {
            mNetworkQueue.add(request);
            return request;
        }

        // Insert request into stage if there's already a request with the same cache key in flight.
        synchronized (mWaitingRequests) {
            String cacheKey = request.getCacheKey();
            if (mWaitingRequests.containsKey(cacheKey)) {
                // There is already a request in flight. Queue up.
                Queue> stagedRequests = mWaitingRequests.get(cacheKey);
                if (stagedRequests == null) {
                    stagedRequests = new LinkedList>();
                }
                stagedRequests.add(request);
                mWaitingRequests.put(cacheKey, stagedRequests);
                if (VolleyLog.DEBUG) {
                    VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);
                }
            } else {
                // Insert 'null' queue for this cacheKey, indicating there is now a request in
                // flight.
                mWaitingRequests.put(cacheKey, null);
                mCacheQueue.add(request);
            }
            return request;
        }
    }

代码的第一部分有一个mCurrentRequests变量,是Set类型的。保存了RequestQueue目前正在处理的所有Request。这个变量很简单,其他也只有在一个地方用到。RequestQueue的cancelAll函数,通过传入的参数RequestFilter的Tag判断是否需要取消Request。

    // Process requests in the order they are added.
   request.setSequence(getSequenceNumber());
   request.addMarker("add-to-queue");

这个部分设置的是序列号,用于判断优先级的一个Integer变量。在Request类的compareTo的方法中用到。

    /**
     * Our comparator sorts from high to low priority, and secondarily by
     * sequence number to provide FIFO ordering.
     */
    @Override
    public int compareTo(Request other) 

getSequenceNumber()的具体是通过AtomicInteger来实现的,是线程安全的。具体可以看java.util.concurrent.atomic这个包。

看接下来的synchronized (mWaitingRequests)部分。先看下mWaitingRequests的定义。

   /**
     * Staging area for requests that already have a duplicate request in flight.
     *
     * 
    *
  • containsKey(cacheKey) indicates that there is a request in flight for the given cache * key.
  • *
  • get(cacheKey) returns waiting requests for the given cache key. The in flight request * is not contained in that list. Is null if no requests are staged.
  • *
*/ private final Map>> mWaitingRequests = new HashMap>>();

如果有当前有重复的request正在被执行,那就把请求放到这个变量中保存,保存的用处可以看下另一处的调用。

    /**
     * Called from {@link Request#finish(String)}, indicating that processing of the given request
     * has finished.
     *
     * 

Releases waiting requests for request.getCacheKey() if * request.shouldCache().

*/ void finish(Request request) { // Remove from the set of requests currently being processed. synchronized (mCurrentRequests) { mCurrentRequests.remove(request); } synchronized (mFinishedListeners) { for (RequestFinishedListener listener : mFinishedListeners) { listener.onRequestFinished(request); } } if (request.shouldCache()) { synchronized (mWaitingRequests) { String cacheKey = request.getCacheKey(); Queue> waitingRequests = mWaitingRequests.remove(cacheKey); if (waitingRequests != null) { if (VolleyLog.DEBUG) { VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.", waitingRequests.size(), cacheKey); } // Process all queued up requests. They won't be considered as in flight, but // that's not a problem as the cache has been primed by 'request'. mCacheQueue.addAll(waitingRequests); } } } }

finish()是request执行完毕后运行的,我们看下和mWaitingRequests相关的地方,如果和当前运行完毕的有相同缓存的话,就会把所有request放到缓冲队列中(具体缓存部分会单独讲解)。

这些就是add方法的内容了。总结下,当一个request添加进来的时候,mCurrentRequests存储一份用于cancel操作。然后添加序列号用于优先级的计算。当requset不需要缓存的时候就直接给网络线程进行网络请求操作,如果需要缓存,就放到mWaitingRequests用于得到缓存结果后的结果返回。这里面涉及到了网络请求序列和缓存请求序列。下两篇文章分别介绍网络请求序列和缓存请求序列的相关内容。

相关文章:
1、Volley源码分析(一)- 初始化

你可能感兴趣的:(Volley源码分析(二)- Request)