您的位置:首页 > 其它

Volley源码学习笔记_CacheDispatcher和NetworkDispatcher

2017-06-08 13:30 253 查看
从之前第一篇第二篇可以看出,NetworkDispatcher和CacheDispatcher是start请求队列的时候创建的线程,在RequestQueue的add方法中我们可以看到请求是先添加到重复请求队列和缓存队列的。缓存队列传递给了CacheDispatcher。那CacheDispatcher中是怎么处理请求队列的?

mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);


上面是在RequestQueue中创建CacheDispatcher传递的参数有缓存队列,请求队列,缓存和mDelivery(用来像UI传递数据,ExecutorDelivery,可以看之前的这里)。下面看一下他的run方法。

public void run() {
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.
//根据key去缓存中获取数据没有的话就想请求加到请求队列去网络获取
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");
//如果存在缓存数据,就调用request的parseNetworkResponse解析返回数据,然后通过mDelivery更新数据
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, new Runnable() {
@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;
}
}
}
}


总结就是:缓存中有数据并且没过期就直接用mDelivery讲数据更新到主线程,否则将请求添加到请求队列让NetworkDispatcher去处理。下面看一下NetworkDispatcher。

new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);


NetworkDispatcher的接受的参数有,请求队列,BasicNetWork,cache以及mDelivery。BasicNetWork之前说过了用来网络请求,mDelivery传递数据更新。看一下他的run方法。

@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
while (true) {
long startTimeMs = SystemClock.elapsedRealtime();
Request<?> request;
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;
}

//设置host主机,访问那台主机,有时候可以是IP,有时候是主机名,例如www.baidu.com,具体去看Request的findDefaultTrafficStatsTag

addTrafficStatsTag(request);

// Perform the network request.
//获取网络请求数据,这个之前说过了,通过BasicNetWork请求网络
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.
//状态码返回304并且请求已经响应了,就不用再请求finish请求队列
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.
//如果设置了需要缓存并且缓存中有东西,就放到mCache中
if (request.shouldCache() && response.cacheEntry != null) {
mCache.put(request.getCacheKey(), response.cacheEntry);
request.addMarker("network-cache-written");
}

// Post the response back.
//设置响应
request.markDelivered();
//将response发到主线程更新数据
mDelivery.postResponse(request, response);
} catch (VolleyError volleyError) {
//发生错误,调用mDelivery将错误信息也发送到主线程
volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
parseAndDeliverNetworkError(request, volleyError);
} catch (Exception e) {
VolleyLog.e(e, "Unhandled exception %s", e.toString());
VolleyError volleyError = new VolleyError(e);
volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs);
mDelivery.postError(request, volleyError);
}
}
}


总结就是:

1.获取请求队列中的请求,没有阻塞,有了请求就向下继续走

2.获取到请求的响应数据(NetworkResponse),如果请求返回304并且已经响应了,这个时候就把请求队列结束掉

3.通过request的parseNetworkResponse返回解析的数据(这个方法是继承Request的时候用户自己实现),如果需要缓存就加到缓存

4.设置请求已经响应了,将数据通过mDelivery发送到主线程更新

5.请求出错也要将相应的错误发送到主线程更新UI。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: