[Android]Volley源码分析(三)
上篇看了关于Request的源码,这篇接着来看下RequestQueue的源码。
RequestQueue类图:
aaarticlea/png;base64,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" alt="" />
RequestQueue是一个请求调度队列,里面包含多个NetworkDispatcher调度器与一个CacheDispatcher调度器
主要属性:
mSequenceGenerator: 请求序号生成器
mWaitingRequests: Staging area for requests that already have a duplicate request in flight. 相当于一个等待队列,根据请求url来将以前发起过的请求先加入这个队列中。避免同样的请求多次发送。
mCurrentRequests: 正在被请求队列处理的请求集合
mCacheQueue: 请求缓存队列,请求可以被缓存也可以不缓存,保存可以缓存的请求
mNetworkQueue: 需要进行网络访问的请求队列
mCache: 可以保存与获取请求响应的缓存,把请求响应保存在disk中
mNetwork: 真正执行Http请求的网络接口
mDelivery: 将请求响应进行解析并交付给请求发起者
mDispatchers: 网络请求调度器,每一个调度器都是一个线程
mCacheDispatcher: 缓存调度器
主要方法:
start(),启动所有调度器线程
/**
* Starts the dispatchers in this queue.
*/
public void start() {
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 (int i = ; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
}
stop()终止所有调度器线程
/**
* Stops the cache and network dispatchers.
*/
public void stop() {
if (mCacheDispatcher != null) {
mCacheDispatcher.quit();
}
for (int i = ; i < mDispatchers.length; i++) {
if (mDispatchers[i] != null) {
mDispatchers[i].quit();
}
}
}
cancellAll(tag) 取消具有tag标识的所有请求
/**
* Cancels all requests in this queue with the given tag. Tag must be non-null
* and equality is by identity.
*/
public void cancelAll(final Object tag) {
if (tag == null) {
throw new IllegalArgumentException("Cannot cancelAll with a null tag");
}
cancelAll(new RequestFilter() {
@Override
public boolean apply(Request<?> request) {
return request.getTag() == tag;
}
});
}
add(Request),将一个请求加入请求队列中。中间有一个判断,如果请求不应被缓存,则只加入mNetworkQueue中,否则根据请求的cacheKey是否已经存在于mWaitingRequests将请求加入mWaitingRequests或mCacheQueue中(同时将cacheKey存入mWaitingRequests)。cacheKey就是请求的Url。
/**
* Adds a Request to the dispatch queue.
* @param request The request to service
* @return The passed-in request
*/
public <T> Request<T> add(Request<T> 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.
18 if (!request.shouldCache()) { //如果请求不应该被缓存,则只加入网络请求队列中
19 mNetworkQueue.add(request);
20 return request;
21 } // 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;
}
}
finish(request), 表示已处理请求request,如果请求被缓存,则清除waitingRequests中的记录,并将其加入mCacheQueue中。
/**
* Called from {@link Request#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>
*/
void finish(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);
}
}
}
}
因为文章是边看源码边记录的,所以一开始完全根据当前的源代码来理解。读的代码越多,理解可能更深入。看完CacheDispatcher与NetworkDispatcher这两个类,这里梳理一下mCurrentRequests, mWaitingRequests,mCacheQueue,mNetworkQueue,mCache,mDispatchers,mCacheDispatcher之间的关系及他们是怎样共同作业来完成一次请求处理的。
1. 当用户以RequestManager.getRequestQueue().add(request)的方式向请求队列中添加一个请求时,即调用RequestQueue.add(request)方法(上面已列出源码), 这个方法首先会把这个request加入mCurrentRequests中,表示这是一个正在被处理的请求。
2. 然后会判断该请求是否可被缓存(通过Request的mShouldCache属性,这个属性默认为true),如果不能,则直接加入mNetworkQueue,由mDispatchers中的某个调度器线程来处理,如果可被缓存(默认都是可被缓存的),则根据Request的cacheKey属性(值为请求的Url)判断请求是否存在于mWaitingRequests这个Map中,如果已经加入,说明之前已经发起过这个请求,那就先将这个请求放入等待队列中,因为请求结果可被缓存,这样等先前那个请求处理完,再处理等待队列中同样的请求(见上面finish()方法),则可以直接从缓存中拿到请求响应,避免了同样的请求多次发送。如果cacheKey不存在于mWaitingRequests中,则将cacheKey存进mWaitingRequests中,表示已发起这样的一个请求,再将这个request加入mCacheQueue中进行处理。
3. mCacheQueue队列中的请求时由mCacheDispatcher这个调度器来调度处理的。 mCacheDispatcher是一个对可缓存的请求进行调度处理的线程,在RequestQueue的start()方法中,对它进行了初始化及启动。
mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
mCacheDispatcher.start();
CacheDispatcher的类图:
aaarticlea/png;base64,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" alt="" />
CacheDispatcher的run()方法
@Override
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.
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, 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;
}
continue;
}
}
}
在这个while循环中,会不断地从mCacheQueue队列中去拿请求,如果请求被取消了,则继续拿下一个请求,否则先从mCache中去查是否缓存了该请求的响应结果,如果没有缓存或者缓存已过期,则将请求加入mNetworkQueue队列中来进行一次网络访问,如果存在缓存并且未过期,则从缓存中取出请求响应并进行解析, 如果缓存没有Soft-expired(Cache.Entry中有两个属性ttl与softTtl,通过这两个值跟当前时间比较来判断缓存是否过期或者“软过期” Soft-expired),则直接通过mDelivery将解析好的结果交付给请求发起者,否则表示虽然缓存没有过期,但是需要通过网络来更新请求响应,则在交付结果之后,将请求加入mNetworkQueue队列发起一个新的网络请求。
4. 在3中知道了当某个请求的响应在mCache中没有缓存或者缓存已过期(包括expired与Soft-expired)时,会把请求加入mNetworkQueue队列中发起一次网络请求。mNetworkQueue这个队列中的请求是由多个NetworkDispatcher调度器来调度处理的。在RequestQueue的start()方法中,有初始化及启动
// Create network dispatchers (and corresponding threads) up to the pool size.
for (int i = ; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
NetworkDispatcher类:
aaarticlea/png;base64,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" alt="" />
NetworkDispatcher的run()方法
@Override
public void run() {
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;
} addTrafficStatsTag(request); // 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, new VolleyError(e));
}
}
}
这个线程会不断地从mNetworkQueue中拿请求,如果请求被取消,则拿下一个,然后通过mNetwork根据情况选择HttpClient或HttpURLConnection(具体怎么选择,后面再说)来进行网络请求,将请求结果进行解析,如果请求可被缓存,则将请求结果进行缓存,最后将结果交付给请求发起者。
其中的addTrafficStatsTag()方法应该是做流量统计用的,request.getTrafficStatsTag()返回的是请求URL中host部分的hashcode
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void addTrafficStatsTag(Request<?> request) {
// Tag the request (if API >= 14)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
TrafficStats.setThreadStatsTag(request.getTrafficStatsTag());
}
}
这样,一次完整的request处理就完成了。 这应该是Volley比较核心的东西了。 先到这,余下的东西后续再看。
[Android]Volley源码分析(三)的更多相关文章
- Android Volley源码分析
今天来顺手分析一下谷歌的volley http通信框架.首先从github上 下载volley的源码, 然后新建你自己的工程以后 选择import module 然后选择volley. 最后还需要更改 ...
- [Android]Volley源码分析(五)
前面几篇通过源码分析了Volley是怎样进行请求调度及请求是如何被实际执行的,这篇最后来看下请求结果是如何交付给请求者的(一般是Android的UI主线程). 类图:
- [Android]Volley源码分析(二)
上一篇介绍了Volley的使用,主要接触了Request与RequestQueue这两个类,这篇就来了解一下这两个类的具体实现. Request类图:
- [Android]Volley源码分析(四)
上篇中有提到NetworkDispatcher是通过mNetwork(Network类型)来进行网络访问的,现在来看一下关于Network是如何进行网络访问的. Network部分的类图:
- Android Volley源码分析及扩展
转载请标明出处: http://www.cnblogs.com/why168888/p/6681232.html 本文出自:[Edwin博客园] Volley 介绍 Android系统中主要提供了两种 ...
- [Android]Volley源码分析(一)
一. 如何使用Volley? 1. 首先定义一个RequestManager类,用来在Android程序启动时对Volley进行初始化.RequestManager为单例类,因为只有在程序启动时调用, ...
- Volley源码分析(三)NetWorkDispatcher分析
NetWorkDispatcher分析 NetWorkDispatcher和CacheDispatcher一样,继承于Thread,在run方法中实现一个无限循环,代码如下 @Override pub ...
- Volley源码分析(2)----ImageLoader
一:imageLoader 先来看看如何使用imageloader: public void showImg(View view){ ImageView imageView = (ImageView) ...
- Appium Android Bootstrap源码分析之启动运行
通过前面的两篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>和<Appium Android Bootstrap源码分析之命令解析 ...
随机推荐
- 学习SQLite之路(三)
20160616更新 参考: http://www.runoob.com/sqlite/sqlite-tutorial.html 1. SQLite PRAGMA:可以用在 SQLite 环境内控制 ...
- 订餐系统之定时器Timer不定时
经过几天漫长的问题分析.处理.测试.验证,定时器Timer终于定时了,于是开始了这篇文章,希望对还在纠结于“定时器Timer不定时”的同学有所帮助,现在的方案,在系统日志中会有警告,如果您有更好的方案 ...
- CSS选择器优先级 CSS权值
计算指定选择器的优先级:重新认识CSS的权重 标签的权值为 0,0,0,1 类的权值为 0,0,1,0 属性选择的权值为 0,0,1,1 ID的权值为 0,1,0,0 important的权值为最高 ...
- 快速向表中插入大量数据Oracle中append与Nologging
来源于:http://blog.sina.com.cn/s/blog_61cd89f60102e7gi.html 当需要对一个非常大的表INSERT的时候,会消耗非常多的资源,因为update表的时候 ...
- Swift开发小技巧--自定义Log
Swift中的自定义Log OC中有宏的定义,可以定义自己的Log,但是Swif中没有宏的定义,想要实现类似OC中的自定义Log,必须实现以下操作 1.在AppDelegate.swift文件中定义一 ...
- 关于 HTTP 请求头的内容
HTTP(HyperTextTransferProtocol)即超文本传输协议,目前网页传输的的通用协议.HTTP协议采用了请求/响应模型,浏览器或其他客户端发出请求,服务器给与响应.就整个网络资源传 ...
- EasyIcon:免费图标搜索和下载平台
EasyIcon是一个为设计师提供免费图标搜索和下载服务的网站. 步骤如下: 第一步,打开EasyIcon网站主页: http://www.easyicon.net/ 第二步,在EasyIcon网站的 ...
- Maven-通过命令操作maven项目
用Maven 命令创建一个简单的Maven项目 在cmd中运行如下命令: mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId ...
- unittest测试驱动之HTMLTestRunner.py
对于自动化来说,测试报告是必须的,在敏捷化的团队中,团队中的成员需要自动化这边提供自动化的测试报告,来判断系统的整体质量以及下一步的测试策略.单元测试库生成测试输出到控制台的窗口上,但是这样的结果看起 ...
- 酶切位点分析(the analysis of enzyme sites)
转自 http://www.yelinsky.com/blog/archives/278.html 稍有修改 默认位点为"CCGG".其他位点分析可修改脚本中的 my $site ...