Volley源码解析(二):RequestQueue

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,这时候再重新请求。

你可能感兴趣的:(Volley源码解析(二):RequestQueue)