在使用Volley进行网络请求,我们通常做法是:
RequestQueue requestQueue=Volley.newRequestQueue(context);
其实,在Volley类里面,有三个 重载的newRequestQueue方法。
newRequestQueue(Context context, HttpStack stack)
newRequestQueueInDisk(Context context, String dir, HttpStack stack)
newRequestQueue(Context context)
通过重载的方法,我们可以传入自己的HttpStack来执行网络请求,HttpStack是网络请求的接口,实现者必须实现其方法。这也是Volley高扩展性的体现。我们还可以通过传入缓存地址,让Volley缓存到我们指定的位置。不论使用哪种方法,下面的代码是这些方法的关键代码:
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack);
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
代码首先判断当前Android设备的版本号,当版本号< 9采用HttpClient进行网络请求,否则采用HttpUrlConnection进行网络请求。其中,HttpClient在Android M开始被废弃,详情查看Android6.0的变化
至于为什么要采用这种方式处理,肯定是做兼容性处理,具体请点击此博客](http://android-developers.blogspot.com/2011/09/androids-http-clients.html)。
同时在程序的最后,调用了RequestQueue的start方法,让Volley开始进行工作。进入到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 = 0; i < mDispatchers.length; i++) {
NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,mCache, mDelivery);
mDispatchers[i] = networkDispatcher;
networkDispatcher.start();
}
在程序开始,先调用stop方法,让正在进行的请求关闭也就是说,每次调用start方法以后,之前未完成的网络请求都被停止。
接着,缓存线程启动,4个网络请求线程开始工作。至于为什么是4个,这是Volley的默认线程数,我们可以通过判断当前的网络状态来动态调整此时线程数。
首先,来看一下缓存线程的工作原理,通过mCacheDispatcher.start();进入到start方法内部,
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.
}
}
});
}
程序首先从缓存队列取出一个请求对象,如果此对象没有取消,就取出缓存,如果缓存为空,说明此请求对象没有被缓存下来,就将此请求对象放入到网络请求队列。如果不为空,继续做是否过期验证,如果没有过期,将缓存组合成响应对象送出去,如若过期,则将此请求对象放入网络请求队里,等待网络请求数据。