标签:
一、Volley框架图
Volley :Volley 对外暴露的 API,类中只有两个函数
通过 newRequestQueue(…) 函数新建并启动一个请求队列RequestQueue
。
Request<T> :表示一个请求的抽象类。
StringRequest
、JsonRequest
、ImageRequest
都是它的子类,表示某种类型的请求。
也可自定义自己的Request
RequestQueue :表示请求队列,一个RequestQueue对象包含:
一个CacheDispatcher
(用于处理走缓存请求的调度线程)、
一个
NetworkDispatcher
数组(默认数组大小为4,用于处理走网络请求的调度线程),
一个ResponseDelivery
(返回结果分发接口),
在start() 函数启动时会创建启动CacheDispatcher
和NetworkDispatchers
。
CacheDispatcher :Cache层中的一个线程,用于调度处理缓存的请求。
启动后会不断从缓存请求队列中取请求处理,队列为空则等待,请求处理结束则将结果传递给ResponseDelivery
去执行后续处理。
当结果未缓存过、缓存失效或缓存需要刷新的情况下,该请求都需要重新进入NetworkDispatcher
去调度处理。
NetworkDispatcher:NetWork层中的一个线程,用于调度处理走网络的请求。
启动后会不断从网络请求队列中取请求处理,队列为空则等待,
请求处理结束则将结果传递给ResponseDelivery
去执行后续处理,并判断结果是否要进行缓存。
ResponseDelivery :返回结果分发接口,在创建RequestQueue对象时进行了初始化
在目前只有基于ExecutorDelivery
的在入参
handler 对应线程内进行分发。
HttpStack :处理 Http 请求,返回请求结果。在newRequestQueue中被初始化。
目前 Volley 中有基于 HttpURLConnection 的HurlStack
和
基于 Apache HttpClient 的HttpClientStack
。
上一篇中已经对其如何根据Android版本进行选择做了解析。
Network :调用HttpStack
处理请求,并将结果转换为可被ResponseDelivery
处理的NetworkResponse
。
在newRequestQueue中被初始化
Cache :缓存请求结果,Volley 默认使用的是基于 sdcard 的DiskBasedCache
。
NetworkDispatcher
得到请求结果后判断是否需要存储在 Cache,CacheDispatcher
会从
Cache 中取缓存结果。
下面附上每个类之间的关系图:
RequestQueue mRequestQueue = Volley.newRequestQueue(this);看一下Volley.newRequestQueue的事务逻辑,Volley类中总共就两个方法:
/** * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. */ public static RequestQueue newRequestQueue(Context context) { return newRequestQueue(context, null); }代码的事务主体在这里:
/** Default on-disk cache directory. */ private static final String DEFAULT_CACHE_DIR = "volley"; /** * 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) { //创建cache File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR); String userAgent = "volley/0"; try { String packageName = context.getPackageName(); PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); userAgent = packageName + "/" + info.versionCode; } catch (NameNotFoundException e) { } /** 根据博文http://blog.csdn.net/guolin_blog/article/details/12452307,HurlStack是用HttpURLConnection实现的; HttpClintStack是由HttpClient实现的;由Android2.3之前的版本宜使用HttpClient,因为其Bug较少; Android2.3之后版本宜使用HttpURLConnection,因其较轻量级且API简单; 故会有此HurlStack和HttpURLConnection的使用分类 */ if (stack == null) { if (Build.VERSION.SDK_INT >= 9) { stack = new HurlStack(); } else { stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); } } //创建以stack为参数的Network对象 Network network = new BasicNetwork(stack); //创建RequestQueue对象 RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network); queue.start();//继续向下分析的入口 return queue; }附I) 、HurlStack中的部分代码,可以看出其是基于HttpURLClient实现的:
private static HttpEntity entityFromConnection(HttpURLConnection connection)对应的HttpClientStack的构造函数可以看出其实基于HttpClient实现的:
public HttpClientStack(HttpClient client) { mClient = client; }而两者都是基于HttpStack接口的:
/** An HTTP stack abstraction.*/ public interface HttpStack { public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError; }
由于Android 2.3版本之前,因为HttpURLConnection的BUG较多,HttpClient的API已经较完备,故宜使用HttpClient,故这里版本9之前,选择使用HttpClientStack;
Android2.3之后版本,HttpURLConnection不断发展,因其较为轻量级,且API使用较为简单,其也在不断优化性能等,故这里使用基于其的HurlStack;
/** * A network performing Volley requests over an {@link HttpStack}. */ public class BasicNetwork implements Network { ... private static int DEFAULT_POOL_SIZE = 4096; protected final HttpStack mHttpStack; protected final ByteArrayPool mPool; public BasicNetwork(HttpStack httpStack) { // If a pool isn't passed in, then build a small default pool that will give us a lot of // benefit and not use too much memory. this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE)); } /** * @param httpStack HTTP stack to be used * @param pool a buffer pool that improves GC performance in copy operations */ public BasicNetwork(HttpStack httpStack, ByteArrayPool pool) { mHttpStack = httpStack; mPool = pool; } ... }
/** Number of network request dispatcher threads to start. */ private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4; public RequestQueue(Cache cache, Network network) { this(cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE); } public RequestQueue(Cache cache, Network network, int threadPoolSize) { this(cache, network, threadPoolSize, new ExecutorDelivery(new Handler(Looper.getMainLooper()))); } /** * Creates the worker pool. Processing will not begin until {@link #start()} is called. * * @param cache A Cache to use for persisting responses to disk * @param network A Network interface for performing HTTP requests * @param threadPoolSize Number of network dispatcher threads to create * @param delivery A ResponseDelivery interface for posting responses and errors */ public RequestQueue(Cache cache, Network network, int threadPoolSize, ResponseDelivery delivery) { mCache = cache; mNetwork = network; mDispatchers = new NetworkDispatcher[threadPoolSize]; mDelivery = delivery; }在这里创建了之前分析中一个重要的对象:NetworkDispatcher;并且可以看到其类似线程池似的,创建了大小为threadPoolSize的NetworkDispatcher数组;其中的处理逻辑暂且不看,首先可以知道其是一个线程:
public class NetworkDispatcher extends Thread
/** * Starts the dispatchers in this queue. */ publicvoid 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(); } } /** Stops the cache and network dispatchers.*/ public void stop() { if (mCacheDispatcher != null) { mCacheDispatcher.quit(); } for (int i = 0; i < mDispatchers.length; i++) { if (mDispatchers[i] != null) { mDispatchers[i].quit(); } } }
/** * The set of all requests currently being processed by this RequestQueue. A Request * will be in this set if it is waiting in any queue or currently being processed by any dispatcher. */ private final Set<Request> mCurrentRequests = new HashSet<Request>(); /** * Adds a Request to the dispatch queue. * @param request The request to service * @return The passed-in request */ 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); //见附I Request设置其对应的RequestQueue synchronized (mCurrentRequests) { //mCurrentRequests表示当前该RequestQueue持有的requests,由HashSet来保存 mCurrentRequests.add(request); } // 为新添加的request进行一系列的初始化设置 request.setSequence(getSequenceNumber()); request.addMarker("add-to-queue"); // 见附II 判断request是否允许缓存 if (!request.shouldCache()) { mNetworkQueue.add(request); return request; } //request如果允许缓存 //Insert request into stage if there's already a request with the same cache key in flight. synchronized (mWaitingRequests) { // 见附III 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; } }附:mCurrentRequests维护了一个正在进行中,尚未完成的请求集合。
private final Set<Request<?>> mCurrentRequests = new HashSet<Request<?>>();附I)、Request.setRequestQueue() 字面上可以看出是Request设置其对应的RequestQueue,简单的setter函数:
/** The request queue this request is associated with. */ private RequestQueue mRequestQueue; /** * Associates this request with the given queue. The request queue will be notified when this * request has finished. */ public void setRequestQueue(RequestQueue requestQueue) { mRequestQueue = requestQueue; }
/** The queue of requests that are actually going out to the network. */ private final PriorityBlockingQueue<Request> mNetworkQueue = new PriorityBlockingQueue<Request>();
/** * Staging area for requests that already have a duplicate request in flight. * <ul> * <li>containsKey(cacheKey) indicates that there is a request in flight for the given cache * key.</li> * <li>get(cacheKey) returns waiting requests for the given cache key. The in flight request * is <em>not</em> contained in that list. Is null if no requests are staged.</li> * </ul> */ private final Map<String, Queue<Request>> mWaitingRequests = new HashMap<String, Queue<Request>>();
1)对于每个新add的request,先获取它的CacheKey;
2)如果当前mWaitingRequests不存在当前cachekey,则会put(cacheKey, null);null表示当前Map中已经存在了一个对应cacheKey的请求;
3)如果mWaitingRequests已经存在了对应的cacheKey,通过get(Key)获取cacheKey对应的Queue;如果Queue为null,由第二步知,当前cacheKey仅仅对应一个request,则新建对应的Map Value值——Queue<Request>(这里由LinkedList来实现),然后添加进去即可;
mCacheQueue和
mNetworkQueue是想对应存在的:
mCacheQueue
放在缓存请求队列中的 Request,将通过缓存获取数据;
mNetworkQueue
放在网络请求队列中的 Request,将通过网络获取数据。
private final PriorityBlockingQueue<Request<?>> mCacheQueue = new PriorityBlockingQueue<Request<?>>(); private final PriorityBlockingQueue<Request<?>> mNetworkQueue = new PriorityBlockingQueue<Request<?>>();
标签:
原文地址:http://blog.csdn.net/woliuyunyicai/article/details/46561699