标签:
一、Volley框架图
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; } }
/** 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来实现),然后添加进去即可;
标签:
原文地址:http://blog.csdn.net/woliuyunyicai/article/details/46559529