/** * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. * * @param context A {@link Context} to use for creating the cache dir. * @return A started {@link RequestQueue} instance. */publicstaticRequestQueuenewRequestQueue(Contextcontext){returnnewRequestQueue(context,(BaseHttpStack)null);}
/** * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. * * @param context A {@link Context} to use for creating the cache dir. * @param stack A {@link BaseHttpStack} to use for the network, or null for default. * @return A started {@link RequestQueue} instance. */publicstaticRequestQueuenewRequestQueue(Contextcontext,BaseHttpStackstack){//这个构造函数负责构建BasicNetworknetwork;if(stack==null){if(Build.VERSION.SDK_INT>=9){network=newBasicNetwork(newHurlStack());}else{// Prior to Gingerbread, HttpUrlConnection was unreliable.// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html// At some point in the future we'll move our minSdkVersion past Froyo and can// delete this fallback (along with all Apache HTTP code).StringuserAgent="volley/0";try{StringpackageName=context.getPackageName();PackageInfoinfo=context.getPackageManager().getPackageInfo(packageName,/* flags= */0);userAgent=packageName+"/"+info.versionCode;}catch(NameNotFoundExceptione){}network=newBasicNetwork(newHttpClientStack(AndroidHttpClient.newInstance(userAgent)));}}else{network=newBasicNetwork(stack);}returnnewRequestQueue(context,network);}
privatestaticRequestQueuenewRequestQueue(Contextcontext,Networknetwork){finalContextappContext=context.getApplicationContext();// Use a lazy supplier for the cache directory so that newRequestQueue() can be called on// main thread without causing strict mode violation.DiskBasedCache.FileSuppliercacheSupplier=newDiskBasedCache.FileSupplier(){privateFilecacheDir=null;@OverridepublicFileget(){if(cacheDir==null){cacheDir=newFile(appContext.getCacheDir(),DEFAULT_CACHE_DIR);}returncacheDir;}};//创建RequestQueueRequestQueuequeue=newRequestQueue(newDiskBasedCache(cacheSupplier),network);//调用start方法queue.start();returnqueue;}
/** * Creates the worker pool. Processing will not begin until {@link #start()} is called. * * @param cache A Cache to use for persisting responses to disk * @param network A Network interface for performing HTTP requests */publicRequestQueue(Cachecache,Networknetwork){this(cache,network,DEFAULT_NETWORK_THREAD_POOL_SIZE);//默认缓存池大小}
/** * Creates the worker pool. Processing will not begin until {@link #start()} is called. * * @param cache A Cache to use for persisting responses to disk * @param network A Network interface for performing HTTP requests * @param threadPoolSize Number of network dispatcher threads to create */publicRequestQueue(Cachecache,Networknetwork,intthreadPoolSize){this(cache,network,threadPoolSize,newExecutorDelivery(newHandler(Looper.getMainLooper())));}
/** Starts the dispatchers in this queue. */publicvoidstart(){stop();// Make sure any currently running dispatchers are stopped.// Create the cache dispatcher and start it.mCacheDispatcher=newCacheDispatcher(mCacheQueue,mNetworkQueue,mCache,mDelivery);mCacheDispatcher.start();// Create network dispatchers (and corresponding threads) up to the pool size.for(inti=0;i<mDispatchers.length;i++){NetworkDispatchernetworkDispatcher=newNetworkDispatcher(mNetworkQueue,mNetwork,mCache,mDelivery);mDispatchers[i]=networkDispatcher;networkDispatcher.start();}}
@Overridepublicvoidrun(){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{processRequest();}catch(InterruptedExceptione){// We may have been interrupted because it was time to quit.if(mQuit){Thread.currentThread().interrupt();return;}VolleyLog.e("Ignoring spurious interrupt of CacheDispatcher thread; "+"use quit() to terminate it");}}}
@VisibleForTestingvoidprocessRequest(finalRequest<?>request)throwsInterruptedException{request.addMarker("cache-queue-take");request.sendEvent(RequestQueue.RequestEvent.REQUEST_CACHE_LOOKUP_STARTED);try{// If the request has been canceled, don't bother dispatching it.if(request.isCanceled()){request.finish("cache-discard-canceled");return;}// Attempt to retrieve this item from cache.Cache.Entryentry=mCache.get(request.getCacheKey());if(entry==null){request.addMarker("cache-miss");// Cache miss; send off to the network dispatcher.//没有在等待队列中添加到请求队列中if(!mWaitingRequestManager.maybeAddToWaitingRequests(request)){mNetworkQueue.put(request);}return;}// If it is completely expired, just send it to the network.if(entry.isExpired()){request.addMarker("cache-hit-expired");request.setCacheEntry(entry);if(!mWaitingRequestManager.maybeAddToWaitingRequests(request)){mNetworkQueue.put(request);}return;}// We have a cache hit; parse its data for delivery back to the request.request.addMarker("cache-hit");Response<?>response=request.parseNetworkResponse(newNetworkResponse(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;if(!mWaitingRequestManager.maybeAddToWaitingRequests(request)){// Post the intermediate response back to the user and have// the delivery then forward the request along to the network.mDelivery.postResponse(request,response,newRunnable(){@Overridepublicvoidrun(){try{mNetworkQueue.put(request);}catch(InterruptedExceptione){// Restore the interrupted statusThread.currentThread().interrupt();}}});}else{// request has been added to list of waiting requests// to receive the network response from the first request once it returns.mDelivery.postResponse(request,response);}}}finally{request.sendEvent(RequestQueue.RequestEvent.REQUEST_CACHE_LOOKUP_FINISHED);}}
@VisibleForTestingvoidprocessRequest(Request<?>request){longstartTimeMs=SystemClock.elapsedRealtime();request.sendEvent(RequestQueue.RequestEvent.REQUEST_NETWORK_DISPATCH_STARTED);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");request.notifyListenerResponseNotUsable();return;}addTrafficStatsTag(request);// Perform the network request.NetworkResponsenetworkResponse=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");request.notifyListenerResponseNotUsable();return;}//负责解析返回值// 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);request.notifyListenerResponseReceived(response);}catch(VolleyErrorvolleyError){volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime()-startTimeMs);parseAndDeliverNetworkError(request,volleyError);request.notifyListenerResponseNotUsable();}catch(Exceptione){VolleyLog.e(e,"Unhandled exception %s",e.toString());VolleyErrorvolleyError=newVolleyError(e);volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime()-startTimeMs);mDelivery.postError(request,volleyError);request.notifyListenerResponseNotUsable();}finally{request.sendEvent(RequestQueue.RequestEvent.REQUEST_NETWORK_DISPATCH_FINISHED);}}
publicExecutorDelivery(finalHandlerhandler){// Make an Executor that just wraps the handler.mResponsePoster=newExecutor(){@Overridepublicvoidexecute(Runnablecommand){handler.post(command);//将结果发动到主线程}};}