/**
* Starts the dispatchers in this queue.
*/publicvoidstart() {
//结束队列中所有的线程
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.//启动网络请求处理线程,默认为5个,可以自己设定 sizefor (int i = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
mCache, mDelivery);
//保存网络请求线程
mDispatchers[i] = networkDispatcher;
//启动网络请求处理线程
networkDispatcher.start();
}
}
启动一个缓存mCacheDispatcher线程,用来读取缓存数据,启动若干个网络请求mDispatchers线程,用来实现网络通信。 mCacheDispatcher线程的 run 方法
@Overridepublicvoidrun() {
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();
//打印 log 信息
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");
Log.i("CacheDispatcher", "没有缓存数据:" + request.getUrl());
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);
Log.i("CacheDispatcher", "缓存数据过期:" + request.getUrl());
mNetworkQueue.put(request);
continue;
}
// We have a cache hit; parse its data for delivery back to the request.// 已经获取到了有效的缓存数据,回调给 request 的parseNetworkResponse,需要自己根据需求来解析数据
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.
Log.i("CacheDispatcher", "获取缓存数据:" + request.getUrl());
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() {
@Overridepublicvoidrun() {
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;
}
}
}
mDispatchers线程的 run 方法
@Overridepublicvoidrun() {
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, new VolleyError(e));
}
}
}
public Request add(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;
}
}
//没有缓存
if (entry == null) {
request.addMarker("cache-miss");
Log.i("CacheDispatcher", "没有缓存数据:" + request.getUrl());
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);
Log.i("CacheDispatcher", "缓存数据过期:" + request.getUrl());
mNetworkQueue.put(request);
continue;
}
2、POST请求 因为在讲 get 请求的时候花了很大篇幅讲原理,所以在 post 请求的时候,需要注意的东西相对来说比较少, 不管是 get 请求还是 post 请求,实现步骤是不会变。 这里post 请求,我们也是用http://www.minongbang.com/test.php?test=minongbang这个 api 来测试! 在前面我们已经讲到了,在同一个应用中共用同一个 RequestQueue,所以第一步可以省略,因为我们已经实现过了。这里直接到定制Request,我们在学习网络编程的时候就已经知道,用 GET方式请求,请求的数据是直接跟在 URL的后面用”?”去分开了,如果有多个数据则用”&”分开。而 POST则把数据直接封装在HTTP的包体中,两者各有优缺点,自己衡量着用。 因为 api 接口还是同一个,所以返回的数据类型肯定是一样的,在解析数据的时候就可以和 GetObjectRequest 复用,所以 PostObjectRequest 的实现可以通过继承GetObjectRequest的方式,也可以直接拷贝一份出来,为了更好的区分,我这里就直接拷贝一份,然后再稍加修改。
/**
* Created by gyzhong on 15/3/1.
*/
public classPostObjectRequest<T> extendsRequest<T> {/**
* 正确数据的时候回掉用
*/private ResponseListener mListener ;
/*用来解析 json 用的*/private Gson mGson ;
/*在用 gson 解析 json 数据的时候,需要用到这个参数*/private Type mClazz ;
/*请求 数据通过参数的形式传入*/private Map<String,String> mParams;
//需要传入参数,并且请求方式不能再为 get,改为 post
public PostObjectRequest(String url, Map<String,String> params,Type type, ResponseListener listener) {
super(Method.POST, url, listener);
this.mListener = listener ;
mGson = new GsonBuilder().excludeFieldsWit