一.volley的用途
主要用于网络操作,获取数据,并缓存到本地SD卡,有默认4个线程处理网络请求。
二.源码解析
1.volley类:获得RequestQueue,并start
public class Volley {
/** Default on-disk cache directory. */
private static final String DEFAULT_CACHE_DIR = "andbase";
/**
* Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.
*
* @param context A {@link Context} to use for creating the cache dir.
* @param stack An {@link HttpStack} to use for the network, or null for default.
* @return A started {@link RequestQueue} instance.
*/
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
File cacheDir = null;
if(!AbFileUtil.isCanUseSD()){
cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
}else{
cacheDir = new File(AbFileUtil.getCacheDownloadDir(context));
}
String userAgent = "andbase/0";
PackageInfo info = AbAppUtil.getPackageInfo(context);
userAgent = info.packageName + "/" + info.versionCode;
if (stack == null) {
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);
<span style="white-space:pre"> </span>//获得requestQueue
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
volley主要方法newRequestQueue(Context,httpStack),context用于生成DiskBasedCache,stack用于生成network.DiskBasedCache是专门管理cache的put,get,将数据写到目标文件夹。network用于网络请求获得response.
注意:sdk>9,网络请求使用HurlStack,内部使用httpconnection。<9使用httpclientstack,内部使用httpclient。httpconnetion API少,bug少,更易扩展。
2.RequestQueue类:
控制中心,处理request,判断后交由CacheQueue或NetworkQueue处理,文件由Cache进行缓存,ResponseDelivery将response传递给request的listener.
主要方法:
方法:start():启动cacheDispatcher和默认4个NetworkDispatcher线程来自动处理request
方法:add(request):添加请求,内部逻辑判断后,将request交由CacheQueue或NetWorkQueue
流程:①mCurrentRequests.add(request)添加request→!request.shouldCache(),不需缓存,就添加到NetworkQueue→判断mWaitingRequests.containsKey(cacheKey)是,mWaitingRequests添加一个stageRequest→
否,mWaitingRequests添加cacheKey,表明正在处理request,同时CacheQueue添加request
方法:finish:结束时从mCurrentRequest里移除,并移除mWaitingRequest的request,如果mWaitingRequest的request不为null,添加到cache里。(为什么?request没处理完被结束掉,mCacheQueue可以继续处理??)
public RequestQueue(Cache cache, Network network, int threadPoolSize,
ResponseDelivery delivery) {
mCache = cache; //用于put,get cache文件
mNetwork = network; //进行网络操作的类,需要传入url
mDispatchers = new NetworkDispatcher[threadPoolSize]; //网络请求分发处理类,是个线程,
mDelivery = delivery; //将response post给request
}
public void start() { //启动cacheDispatcher和默认4个NetworkDispatcher线程来自动处理request
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();
}
}
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;
}
}