您的位置:首页 > 产品设计 > UI/UE

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,这时候再重新请求。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: