Volley 核心源码解析(二)
请求队列RequestQueue
每一个使用过Volley的同行们都用过RequestQueue.add(request)这个方法,看看这个方法到底做了什么:
public<T>Request<T>add(Request<T>request){
//Tagtherequestasbelongingtothisqueueandaddittothesetofcurrentrequests.
request.setRequestQueue(this);
synchronized(mCurrentRequests){
mCurrentRequests.add(request);
}
//Processrequestsintheordertheyareadded.
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue");
//Iftherequestisuncacheable,skipthecachequeueandgostraighttothenetwork.
if(!request.shouldCache()){
mNetworkQueue.add(request);
returnrequest;
}
//Insertrequestintostageifthere'salreadyarequestwiththesamecachekeyinflight.
synchronized(mWaitingRequests){
StringcacheKey=request.getCacheKey();
if(mWaitingRequests.containsKey(cacheKey)){
//Thereisalreadyarequestinflight.Queueup.
Queue<Request<?>>stagedRequests=mWaitingRequests.get(cacheKey);
if(stagedRequests==null){
stagedRequests=newLinkedList<Request<?>>();
}
stagedRequests.add(request);
mWaitingRequests.put(cacheKey,stagedRequests);
if(VolleyLog.DEBUG){
VolleyLog.v("RequestforcacheKey=%sisinflight,puttingonhold.",cacheKey);
}
}else{
//Insert'null'queueforthiscacheKey,indicatingthereisnowarequestin
//flight.
mWaitingRequests.put(cacheKey,null);
mCacheQueue.add(request);
}
returnrequest;
}
}
我们看到这里面有两个被用synchronized块锁住的对象:mCurrentRequests,mWaitingRequests
那么这两个是什么呢?
/**
*ThesetofallrequestscurrentlybeingprocessedbythisRequestQueue.ARequest
*willbeinthissetifitiswaitinginanyqueueorcurrentlybeingprocessedby
*anydispatcher.
*/
privatefinalSet<Request<?>>mCurrentRequests=newHashSet<Request<?>>();
/**
*Stagingareaforrequeststhatalreadyhaveaduplicaterequestinflight.
*
*
*<li>containsKey(cacheKey)indicatesthatthereisarequestinflightforthegivencache
*key.</li>
*<li>get(cacheKey)returnswaitingrequestsforthegivencachekey.Theinflightrequest
*isnotcontainedinthatlist.Isnullifnorequestsarestaged.</li>
*
*/
privatefinalMap<String,Queue<Request<?>>>mWaitingRequests=
newHashMap<String,Queue<Request<?>>>();
看英文注释意思:
mCurrentRequests大意是,当前在这个队列里所有正在被执行的请求的集合。所有的正在被执行的或者在队列中等待执行的请求都应该放进这个set集合中。
mWaitingRequests:包含重复请求的临时区域,
通俗的说就是一个是所有正在执行和等待执行的请求集合,另一个是存放重复请求的临时区域是一个map.
当我们调用add方法的时候首先是把请求加入到mCurrentRequests中,当然咯,这个过程是同步的。
此时volley还给每个请求设置了序号和备注:
request.setSequence(getSequenceNumber());
request.addMarker("add-to-queue");
接下来如下:
if(!request.shouldCache()){
mNetworkQueue.add(request);
returnrequest;
}
这段代码很有意思,如果一个请求不支持被缓存的话,马上就把这个请求交给mNetworkQueue
中去执行,后面的代码不再执行。
mNetworkQueue的定义如下:
/**Thequeueofrequeststhatareactuallygoingouttothenetwork.*/
privatefinalPriorityBlockingQueue<Request<?>>mNetworkQueue=
newPriorityBlockingQueue<Request<?>>();
这是一个全新的阻塞式的队列。这个队列的作用后面再讲。
在Request类中我们看到
privatebooleanmShouldCache=true;
说明Volley中默认每一个请求都是要被缓存的。
接下来通过Request的cacheKey区分请求是否重复,如果有重复请求,就把这个请求所属的队列拿出来,然后把新的请求加到队列中,再存到mWaitingRequests中。
如果mWaitingRequests中没有这个请求,就用这个请求的cacheKey去保存一个NULL值,
言简意赅的说;每一个请求都会在执行的同时放到mWaitingRequests中,同时也要被放进缓存队列中,
mCacheQueue:
privatefinalPriorityBlockingQueue<Request<?>>mCacheQueue=
newPriorityBlockingQueue<Request<?>>();
mCacheQueue中的请求何时执行,后面会讲到。
下一节Volley的任务调度模型http://f303153041.iteye.com/blog/2281352