RequestQueue有三个重要函数,分别是start(),add(),finish();接下来一一讲解
/**
* Starts the dispatchers in this queue.
*/
public voidstart() {
stop(); // Make sure any currently running dispatchers are stopped.
// Create the cache dispatcher and start it.
mCacheDispatcher = new CacheDispatcher( mCacheQueue,mNetworkQueue,mCache,mDelivery);
mCacheDispatcher .start();
// Create network dispatchers (and corresponding threads) up to the pool size.
for (inti =0;i <mDispatchers.length;i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue,mNetwork,
mCache,mDelivery);
mDispatchers [i] = networkDispatcher;
networkDispatcher.start();
}
}
start函数里涉及两个类,CacheDispatcher如果这个request需要缓存或者缓存里有它的数据并且不过期,就交给它去取得缓存数据。
NetworkDispatcher是调用BasicNetWork的网络请求,也就是说网络请求是在这里开始执行的,如果没有设置线程大小的话,只有四个网络线程处理网络请求。
/**
* Adds a Request to the dispatch queue.
* @param
request
The request to service
* @returnThe 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<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
;
}
}
/** Whether or not responses to this request should be cached. */
private boolean
mShouldCache=
true;
如果不需要处理缓存就直接交给NetWorkDispatcher处理,Volley默认是要处理缓存。否则,如果这个请求已经存在,就放到等待队列里,否则就加入CacheDispather和等待队列。
接下来就是何时从等待队列里移除请求即何时调用finish()。
/**
* Called from {@linkRequest#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>
*/
void
finish
(Request request) {
// Remove from the set of requests currently being processed.
synchronized
(
mCurrentRequests
) {
mCurrentRequests
.remove(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)
;
}
}
}
}
是当Request请求成功,失败或者取消时,Request自动调用的:
void
finish
(
final
String tag) {
if
(
mRequestQueue
!=
null
) {
mRequestQueue
.finish(
this
)
;
}
接下来是NetWorkDispather也就是网络请求:
@Override
public void
run
() {
Process.setThreadPriority(Process.
THREAD_PRIORITY_BACKGROUND
)
;
Request request
;
while
(
true
) {
try
{
// Take a request from the queue.
request =
mQueue
.take()
;
}
catch
(InterruptedException e) {
// We may have been interrupted because it was time to quit.
if
(
mQuit
) {
return;
}
continue;
}
try
{
request.addMarker(
"network-queue-take"
)
;
// If the request was cancelled already, do not perform the
// network request.
if
(request.isCanceled()) {
request.finish(
"network-discard-cancelled"
)
;
continue;
}
// Tag the request (if API >= 14)
if
(Build.VERSION.
SDK_INT
>= Build.VERSION_CODES.
ICE_CREAM_SANDWICH
) {
TrafficStats.setThreadStatsTag(request.getTrafficStatsTag())
;
}
// Perform the network request.
NetworkResponse networkResponse =
mNetwork
.performRequest(request)
;
request.addMarker(
"network-http-complete"
)
;
// If the server returned 304 AND we delivered a response already,
// we're done -- don't deliver a second identical response.
if
(networkResponse.
notModified
&& request.hasHadResponseDelivered()) {
request.finish(
"not-modified"
)
;
continue;
}
// Parse the response here on the worker thread.
Response<?> response = request.parseNetworkResponse(networkResponse)
;
request.addMarker(
"network-parse-complete"
)
;
// Write to cache if applicable.
//
TODO: Only update cache metadata instead of entire record for 304s.
if
(request.shouldCache() && response.
cacheEntry
!=
null
) {
mCache
.put(request.getCacheKey()
,
response.
cacheEntry
)
;
request.addMarker(
"network-cache-written"
)
;
}
// Post the response back.
request.markDelivered()
;
mDelivery
.postResponse(request
,
response)
;
}
catch
(VolleyError volleyError) {
parseAndDeliverNetworkError(request
,
volleyError)
;
}
catch
(Exception e) {
VolleyLog.e(e
,
"Unhandled exception %s"
,
e.toString())
;
mDelivery
.postError(request
, new
VolleyError(e))
;
}
}
}
如果mNetWorkQueue有请求加入了,mqueue.take就有值返回,否则就一直阻塞。
如果没有取消并且没有退出就执行网络请求,如果需要写入缓存就写入缓存,最后开始发给Handler,也就是主线程处理请求结果,这个以后再讲。
最后是CacheDispathcer类:
@Override
public void
run
() {
if
(
DEBUG
) VolleyLog. v(
"start new dispatcher"
)
;
Process.setThreadPriority(Process.
THREAD_PRIORITY_BACKGROUND
)
;
// Make a blocking call to initialize the cache.
mCache .initialize()
;
while
(
true
) {
try
{
// Get a request from the cache triage queue, blocking until
// at least one is available.
final
Request request =
mCacheQueue
.take()
;
request.addMarker(
"cache-queue-take"
)
;
// If the request has been canceled, don't bother dispatching it.
if
(request.isCanceled()) {
request.finish(
"cache-discard-canceled"
)
;
continue;
}
// Attempt to retrieve this item from cache.
Cache.Entry entry = mCache.get(request.getCacheKey())
;
if
(entry ==
null
) {
request.addMarker(
"cache-miss"
)
;
// Cache miss; send off to the network dispatcher.
mNetworkQueue
.put(request)
;
continue;
}
// If it is completely expired, just send it to the network.
if
(entry.isExpired()) {
request.addMarker(
"cache-hit-expired"
)
;
request.setCacheEntry(entry)
;
mNetworkQueue
.put(request)
;
continue;
}
// We have a cache hit; parse its data for delivery back to the request.
request.addMarker(
"cache-hit"
)
;
Response<?> response = request.parseNetworkResponse(
new
NetworkResponse(entry.
data
,
entry.
responseHeaders
))
;
request.addMarker(
"cache-hit-parsed"
)
;
if
(!entry.refreshNeeded()) {
// Completely unexpired cache hit. Just deliver the response.
mDelivery
.postResponse(request
,
response)
;
}
else
{
// Soft-expired cache hit. We can deliver the cached response,
// but we need to also send the request to the network for
// refreshing.
request.addMarker(
"cache-hit-refresh-needed"
)
;
request.setCacheEntry(entry)
;
// Mark the response as intermediate.
response.
intermediate
=
true;
// Post the intermediate response back to the user and have
// the delivery then forward the request along to the network.
mDelivery
.postResponse(request
,
response
, new
Runnable() {
@Override
public void
run
() {
try
{
mNetworkQueue
.put(
request
)
;
}
catch
(InterruptedException e) {
// Not much we can do about this.
}
}
})
;
}
}
catch
(InterruptedException e) {
// We may have been interrupted because it was time to quit.
if
(
mQuit
) {
return;
}
continue;
}
}
}
这个类更好理解,如果缓存里没有或者缓存过期,就加入到mNetWorkQueue,否则就取缓存里的结果直接返回。在这里重点说下需要刷新那块代码,设置立即刷新,并交给分发处理,这时候会先返回结果给主线程,再把请求交给NetworkDispatcher,这时候再重新请求。