Volley源码解析(二):RequestQueue
2015-12-08 17:59
330 查看
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.
* @paramrequestThe
request to service
* @returnThe passed-in request
*/
publicRequestadd(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;
}
}
[align=left]/** Whether or not responses to this request should be cached. */[/align]
private booleanmShouldCache=
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>
*/
voidfinish(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自动调用的:
voidfinish(finalString
tag) {
if
(mRequestQueue!=null)
{
mRequestQueue
.finish(this);
}
接下来是NetWorkDispather也就是网络请求:
@Override
public voidrun()
{
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, newVolleyError(e));
}
}
}
如果mNetWorkQueue有请求加入了,mqueue.take就有值返回,否则就一直阻塞。
如果没有取消并且没有退出就执行网络请求,如果需要写入缓存就写入缓存,最后开始发给Handler,也就是主线程处理请求结果,这个以后再讲。
最后是CacheDispathcer类:
@Override
public voidrun()
{
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,
newRunnable() {
@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,这时候再重新请求。
/**
* 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.
* @paramrequestThe
request to service
* @returnThe passed-in request
*/
publicRequestadd(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;
}
}
[align=left]/** Whether or not responses to this request should be cached. */[/align]
private booleanmShouldCache=
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>
*/
voidfinish(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自动调用的:
voidfinish(finalString
tag) {
if
(mRequestQueue!=null)
{
mRequestQueue
.finish(this);
}
接下来是NetWorkDispather也就是网络请求:
@Override
public voidrun()
{
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, newVolleyError(e));
}
}
}
如果mNetWorkQueue有请求加入了,mqueue.take就有值返回,否则就一直阻塞。
如果没有取消并且没有退出就执行网络请求,如果需要写入缓存就写入缓存,最后开始发给Handler,也就是主线程处理请求结果,这个以后再讲。
最后是CacheDispathcer类:
@Override
public voidrun()
{
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,
newRunnable() {
@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,这时候再重新请求。
相关文章推荐
- ZZULIOJ 1801 xue姐的小动物
- POJ 3080 Blue Jeans
- 学习 easyui 之一:easyloader 分析与使用
- UI第十九天:数据库
- pcduino nfs挂在光盘
- UItextView,UIscrollView,UITableViewCell三种能够使页面滑动控件的总结(1)
- easyui layout 左右面板折叠后 显示标题
- SunCertPathBuilderException: unable to find valid certification path to requested target
- ecshop后台编辑器替换成ueditor编辑器
- UITableView普通的样式
- j2ee四大作用域pagecontext,request,session,ServletContext
- 如何更好地限制一个UITextField的输入长度
- JUinte测试
- UItableView的性能优化
- IOS之UITextField 禁止粘贴
- 一个简单的Web UI自动化测试框架Java实现
- AlertDialog.Builder的使用
- 杭电 OJ1005Number Sequence(循环节)
- Codeforces 374D Inna and Sequence 二分法+树状数组
- Android 5.0 源码分析 Handler Looper MessageQueue 底层原理