Volley 核心源码解析(三)
Volley的任务调度模型
接着上一节的RequestQueue,在Volley初始化RequestQueue的时候会执行RequestQueue的start()方法,在start方法中初始化了,缓存调度器和网络调度器。
publicvoidstart(){
stop();//Makesureanycurrentlyrunningdispatchersarestopped.
//Createthecachedispatcherandstartit.
mCacheDispatcher=newCacheDispatcher(mCacheQueue,mNetworkQueue,mCache,mDelivery);
mCacheDispatcher.start();
//Createnetworkdispatchers(andcorrespondingthreads)uptothepoolsize.
for(inti=0;i<mDispatchers.length;i++){
NetworkDispatchernetworkDispatcher=newNetworkDispatcher(mNetworkQueue,mNetwork,
mCache,mDelivery);
mDispatchers[i]=networkDispatcher;
networkDispatcher.start();
}
}
看看NetworkDispatcher和CacheDispatcher是什么东东?
NetworkDispatcherextendsThread
CacheDispatcherextendsThread
结果两个都是线程类。
再看看循环体中往一个叫做mDispatchers[i]的数组中赋值了若干NetworkDispatcher,且每个NetworkDispatcher都在创建的时候就启动了。
找到mDispatchers的定义:
privatestaticfinalintDEFAULT_NETWORK_THREAD_POOL_SIZE=4;
mDispatchers=newNetworkDispatcher[threadPoolSize];
原来是个默认4个元素的线程组。
看到这里我似乎想到了线程池的基本概念,没错这就是个线程池。
看看具体的NetworkDispatcher是什么样的?
做过JAVA开发的都知道继承thread类一定要重写run()方法
在NetworkDispatcher中run方法如下:
方法太长一段一段的来看哈
因为是要做线程池嘛,所以线程要一直工作,所以一进run方法就是while(true){}
了,
Request<?>request=mQueue.take();
mQueue:mNetworkQueue
在PriorityBlockingQueue队列中take方法如下:
publicEtake()throwsInterruptedException{
finalReentrantLocklock=this.lock;
lock.lockInterruptibly();
Eresult;
try{
while((result=dequeue())==null)
notEmpty.await();
}finally{
lock.unlock();
}
returnresult;
}
意思就是加锁-->取出一个请求->释放锁->原队列中请求减少一个
这样就保证了使用volley发送请求的时候能按照发送请求的顺序去执行。
接下来从队列中取出请求之后,给请求设置备注,判断请求时否被取消,如果被取消就finish。
//Iftherequestwascancelledalready,donotperformthe
//networkrequest.
if(request.isCanceled()){
request.finish("network-discard-cancelled");
continue;
}
紧接着,执行该请求:
//Performthenetworkrequest.
NetworkResponsenetworkResponse=mNetwork.performRequest(request);
后面就是对networkResponse的一些状态判断和解析。
Response<?>response=request.parseNetworkResponse(networkResponse);
在volley中解析NetworkResponse的具体方法交给Request的子类去实现。如,ImageRequest,JsonRequest,StringRequest等
同时,缓存这个已经执行的请求:
if(request.shouldCache()&&response.cacheEntry!=null){
mCache.put(request.getCacheKey(),response.cacheEntry);
request.addMarker("network-cache-written");
}
看到这里,我们可以得出一个结论,Volley初始化RequestQueue的时候创建了一个
默认4个大小的线程池,每个线程同步的从PriorityBlockingQueue类型的请求队列中拿出一个请求并执行。
接下来看看CacheDispatcher缓存任务调度:
/**Thequeueofrequestscominginfortriage.*/
privatefinalBlockingQueue<Request<?>>mCacheQueue;
/**Thequeueofrequestsgoingouttothenetwork.*/
privatefinalBlockingQueue<Request<?>>mNetworkQueue;
与NetworkDispatcher不同的是CacheDispatcher不仅有缓存队列还有请求队列,
同样是while(true){request=mCacheQueue.take();;...}
不停的从mCacheQueue拿出缓存过的请求:
//Attempttoretrievethisitemfromcache.
Cache.Entryentry=mCache.get(request.getCacheKey());
if(entry==null){
request.addMarker("cache-miss");
//Cachemiss;sendofftothenetworkdispatcher.
mNetworkQueue.put(request);
continue;
}
这里看到被缓存的请求时根据请求的cacheKey从cache中取出,如果取出的缓存为空,直接把请求放到mNetworkQueue,也就是说把请求交给了NetworkDispatcher去执行。
如果请求的缓存对象过期,同上:
//Ifitiscompletelyexpired,justsendittothenetwork.
if(entry.isExpired()){
request.addMarker("cache-hit-expired");
request.setCacheEntry(entry);
mNetworkQueue.put(request);
continue;
}
这里我们看到一个关键性的代码:
Response<?>response=request.parseNetworkResponse(
newNetworkResponse(entry.data,entry.responseHeaders));
这是什么意思呢?
Volley不仅缓存了请求本身,而且缓存了请求的响应结果,此时做的就是从缓存中取出响应的结果,这样就不用再发请求去服务器上了。
接下来,
if(!entry.refreshNeeded()){
//Completelyunexpiredcachehit.Justdelivertheresponse.
mDelivery.postResponse(request,response);
}else{
//Soft-expiredcachehit.Wecandeliverthecachedresponse,
//butweneedtoalsosendtherequesttothenetworkfor
//refreshing.
request.addMarker("cache-hit-refresh-needed");
request.setCacheEntry(entry);
//Marktheresponseasintermediate.
response.intermediate=true;
//Posttheintermediateresponsebacktotheuserandhave
//thedeliverythenforwardtherequestalongtothenetwork.
finalRequest<?>finalRequest=request;
mDelivery.postResponse(request,response,newRunnable(){
@Override
publicvoidrun(){
try{
mNetworkQueue.put(finalRequest);
}catch(InterruptedExceptione){
//Notmuchwecandoaboutthis.
}
}
});
}
如果缓存数据不需要刷新,只需要用回掉接口返回值,反之,把请求放入mNetworkQueue,等待NetworkDispatcher执行。
至此,Volley的线程模型分析告一段落,我们看到了线程组NetworkDispatcher[]和单线程CacheDispatcher通过两个BlockingQueue巧妙地实现了网络请求任务的交替轮换。
下一节Volley的缓存http://f303153041.iteye.com/blog/2281360