美文网首页
Volley源码分析(二)- Request

Volley源码分析(二)- Request

作者: 似衡 | 来源:发表于2016-11-14 16:22 被阅读50次

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

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

所有网络请求的基类,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<T> 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 <T> Request<T> add(Request<T> 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<Request<?>> stagedRequests = mWaitingRequests.get(cacheKey);
                if (stagedRequests == null) {
                    stagedRequests = new LinkedList<Request<?>>();
                }
                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<T> other) 

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

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

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

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

    /**
     * Called from {@link Request#finish(String)}, indicating that processing of the given request
     * has finished.
     *
     * <p>Releases waiting requests for <code>request.getCacheKey()</code> if
     *      <code>request.shouldCache()</code>.</p>
     */
    <T> void finish(Request<T> request) {
        // Remove from the set of requests currently being processed.
        synchronized (mCurrentRequests) {
            mCurrentRequests.remove(request);
        }
        synchronized (mFinishedListeners) {
          for (RequestFinishedListener<T> listener : mFinishedListeners) {
            listener.onRequestFinished(request);
          }
        }

        if (request.shouldCache()) {
            synchronized (mWaitingRequests) {
                String cacheKey = request.getCacheKey();
                Queue<Request<?>> 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

      本文链接:https://www.haomeiwen.com/subject/opihpttx.html