上一篇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源码分析(一)- 初始化