Volley 分析
2016-07-13 16:17
399 查看
Volley 中文翻译是齐射,这个名字也简要的说明了 Volley 的特点,适用于数据量小,频繁通信。
一、总体设计
1、总体设计图
2. 总体的流程图
(图片来自codeKK)
二、主要类
1、Request
抽象类,请求对象。直接子类: ImageRequest, JsonArrayRequest, JsonObjectRequest, JsonRequest, 以及StringRequest.
2、Network
接口,用于网络请求, 实现类是 BasicNetwork;
3、CacheDispatcher
一个线程,处理磁盘缓存请求;
4、NetworkDispatcher
一个线程,处理网络请求;
5、HttpStack
接口,根据给定的参数,执行一个网络请求,并返回请求结果;
实现类是基于 HttpURLConnection 的 HurlStack, 在 SDK >= 9 版本上使用;另外一个是基于 HttpClient 的HttpClientStack, 在 SDK < 9 版本以下使用;
6、ResponseDelivery
接口,用于分发结果,实现类是 ExecutorDelivery;
7、Cache
接口, 缓存请求结果,实现类是磁盘缓存的 DiskBasedCache.
三、具体类分析
1、Request
Request 是一个抽象类,子类需要重写主要的两个方法:
分发结果给 listener
abstract protected void deliverResponse(T response);
将网络请求返回的数据转化成请求的数据类型,在工作线程中被调用
abstract protected Response<T> parseNetworkResponse(NetworkResponse response);
2、Network
Network 是一个接口,它的实现类需要实现方法,执行一个特定的请求
public NetworkResponse performRequest(Request<?> request) throws VolleyError;
实现类 BasicNetwork 中的该方法,在工作线程中被调用
3、CacheDispatcher
一个线程,通过它的 start() 方法启动
(1)主要的成员变量
主要步骤是,从缓存队列中取出一个请求,然后从缓存中取数据,判读数据是否需要更新、过时等信息,再者将数据转化成请求的数据格式,最后进行分发;
4、NetworkDispatcher
一个线程,通过它的 start() 方法启动。在 RequestQueue 中会启动四个默认的 NetworkDispatcher 用于网络请求;
(1) 主要成员变量
(2) 主要步骤
从请求队列中取出一个请求,然后进行网络请求并返回请求结果,将返回的数据转化成请求的数据格式类型,如果需要缓存则放到缓存中,最后是分发结果;
5、HttpStack
一个接口,实现类需要实现执行一个 HTTP 请求
实现类 HttpClientStack, 基于 HttpClient
6、ResponseDelivery
接口,实现类是 ExecutorDelivery, 根据传进来 Handler 所在线程内分发结果
在调用 Volley.newRequestQueue(...) 的时候,会生成一个新的 RequestQueue 对象,同时生成一个传入主线程 Handler 的
ExecutorDelivery;
ExecutorDelivery 类
将分发结果传递给 listener
网络请求结果分发流程图
说明:
(1)、NetworkDispatcher 中将网络请求的结果调用方法 ReponseDelivery.postResponse(...) 方法进行分发,这是在 workerThread中, ResponseDelivery 只是接口,最终还是会调用实现类 ExecutorDelivery.postResponse(...)
方法;
(2)、ExecutroDelivery.postResonse(...) 方法用 抱箍 handler 的 Executor 将 ResponseDeliveryRunnable 任务 post 回到主线程执行;
(3)、然后将网络请求结果传递给 listener;
7、Cache
接口,实现类是 DiskBasedCache, 磁盘缓存,默认是大小时 5M
8、RequestQueue
核心类
主要成员变量:
自动生成请求序列号
mSequenceGenerator = new AtomicInteger()
等待 Set
mWaitingRequests = new HashMap<String, Queue<Request<?>>>();
当前缓存的 Set
mCurrentRequests = new HashSet<Request<?>>();
缓存队列
PriorityBlockingQueue<Request<?>> mCacheQueue;
网络请求队列
PriorityBlockingQueue<Request<?>> mNetworkQueue;
网络
Network mNetwork;
分发结果
ResponseDelivery mDelivery;
网络线程
NetworkDispatcher[] mDispatchers;
磁盘缓存线程
CacheDispatcher mCacheDispatcher;
(1)、生成一个 RequestQueue 对象时,传入一个主线程的 Handler, 用于分发结果;
(2)、添加一个请求
(3)、调用 RequestQueue 的 start() 方法,会启动一个磁盘缓存线程和四个网络请求线程
9、Volley
对外提供 API, 并且启动请求队列 RequestQueue
三、使用例子
已 StringRequest 为例
分析完成。
一、总体设计
1、总体设计图
2. 总体的流程图
(图片来自codeKK)
二、主要类
1、Request
抽象类,请求对象。直接子类: ImageRequest, JsonArrayRequest, JsonObjectRequest, JsonRequest, 以及StringRequest.
2、Network
接口,用于网络请求, 实现类是 BasicNetwork;
3、CacheDispatcher
一个线程,处理磁盘缓存请求;
4、NetworkDispatcher
一个线程,处理网络请求;
5、HttpStack
接口,根据给定的参数,执行一个网络请求,并返回请求结果;
实现类是基于 HttpURLConnection 的 HurlStack, 在 SDK >= 9 版本上使用;另外一个是基于 HttpClient 的HttpClientStack, 在 SDK < 9 版本以下使用;
6、ResponseDelivery
接口,用于分发结果,实现类是 ExecutorDelivery;
7、Cache
接口, 缓存请求结果,实现类是磁盘缓存的 DiskBasedCache.
三、具体类分析
1、Request
Request 是一个抽象类,子类需要重写主要的两个方法:
分发结果给 listener
abstract protected void deliverResponse(T response);
将网络请求返回的数据转化成请求的数据类型,在工作线程中被调用
abstract protected Response<T> parseNetworkResponse(NetworkResponse response);
2、Network
Network 是一个接口,它的实现类需要实现方法,执行一个特定的请求
public NetworkResponse performRequest(Request<?> request) throws VolleyError;
实现类 BasicNetwork 中的该方法,在工作线程中被调用
@Override public NetworkResponse performRequest(Request<?> request) throws VolleyError { // 请求开始时间 long requestStart = SystemClock.elapsedRealtime(); while (true) { HttpResponse httpResponse = null; byte[] responseContents = null; // 请求头部 Map<String, String> responseHeaders = Collections.emptyMap(); try { // Gather headers. Map<String, String> headers = new HashMap<String, String>(); addCacheHeaders(headers, request.getCacheEntry()); // 执行网络请求返回请求结果 httpResponse = mHttpStack.performRequest(request, headers); StatusLine statusLine = httpResponse.getStatusLine(); int statusCode = statusLine.getStatusCode(); responseHeaders = convertHeaders(httpResponse.getAllHeaders()); // Handle cache validation. if (statusCode == HttpStatus.SC_NOT_MODIFIED) { Entry entry = request.getCacheEntry(); if (entry == null) { return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); } // A HTTP 304 response does not have all header fields. We // have to use the header fields from the cache entry plus // the new ones from the response. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5 entry.responseHeaders.putAll(responseHeaders); return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data, entry.responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); } // Handle moved resources if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) { String newUrl = responseHeaders.get("Location"); request.setRedirectUrl(newUrl); } // Some responses such as 204s do not have content. We must check. if (httpResponse.getEntity() != null) { responseContents = entityToBytes(httpResponse.getEntity()); } else { // Add 0 byte response as a way of honestly representing a // no-content request. responseContents = new byte[0]; } // if the request is slow, log it. long requestLifetime = SystemClock.elapsedRealtime() - requestStart; logSlowRequests(requestLifetime, request, responseContents, statusLine); if (statusCode < 200 || statusCode > 299) { throw new IOException(); } return new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart); } ... } }说明:NetworkResponse 只是一个封装请求返回结果的类。
3、CacheDispatcher
一个线程,通过它的 start() 方法启动
(1)主要的成员变量
/** The queue of requests coming in for triage.*/ // 缓存请求队列 private final BlockingQueue<Request<?>> mCacheQueue; /** The queue of requests going out to the network. */ // 网络请求队列 private final BlockingQueue<Request<?>> mNetworkQueue; /** The cache to read from. */ // 缓存类 private final Cache mCache; /** For posting responses. */ // 分发结果类 private final ResponseDelivery mDelivery;(2)请求过程
主要步骤是,从缓存队列中取出一个请求,然后从缓存中取数据,判读数据是否需要更新、过时等信息,再者将数据转化成请求的数据格式,最后进行分发;
@Override public void run() { if (DEBUG) VolleyLog.v("start new dispatcher"); // 设置为后台线程 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); // Make a blocking call to initialize the cache. // 缓存的初始化 mCache.initialize(); // DiskBasedCache.initialize() Request<?> request; while (true) { // 死循环,会不断的从队列中取请求 // release previous request object to avoid leaking request object when mQueue is drained. request = null; try { // Take a request from the queue. // 1、从队列中取出一个请求 request = mCacheQueue.take(); } catch (InterruptedException e) { // We may have been interrupted because it was time to quit. if (mQuit) { return; } continue; } try { 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. // 2.从缓存中拿数据,如果是空的,则放到一个网络请求队列中,然后跳过 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. // 3.将缓存中拿到的数据转化成请求的数据格式,例如 String, JSON 之类的。 request.addMarker("cache-hit"); Response<?> response = request.parseNetworkResponse(new NetworkResponse(entry.data, entry.responseHeaders)); request.addMarker("cache-hit-parsed"); // 4.如果缓存数据不需要刷新,直接分发结果;否则在分发结果的同时也放到网络请求中,再一次请求。 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. final Request<?> finalRequest = request; mDelivery.postResponse(request, response, new Runnable() { @Override public void run() { try { // 放入到网络请求队列中 mNetworkQueue.put(finalRequest); } catch (InterruptedException e) { // Not much we can do about this. } } }); } } catch (Exception e) { VolleyLog.e(e, "Unhandled exception %s", e.toString()); } } }
4、NetworkDispatcher
一个线程,通过它的 start() 方法启动。在 RequestQueue 中会启动四个默认的 NetworkDispatcher 用于网络请求;
(1) 主要成员变量
/** The queue of requests to service. */ // 请求队列 private final BlockingQueue<Request<?>> mQueue; /** The network interface for processing requests. */ // 网络请求接口,用于网络请求 private final Network mNetwork; /** The cache to write to. */ // 缓存类,用于存储请求回来的数据 private final Cache mCache; /** For posting responses and errors. */ // 分发结果类 private final ResponseDelivery mDelivery;
(2) 主要步骤
从请求队列中取出一个请求,然后进行网络请求并返回请求结果,将返回的数据转化成请求的数据格式类型,如果需要缓存则放到缓存中,最后是分发结果;
@Override public void run() { // 设置为后台线程 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); Request<?> request; while (true) { // 开始时间 long startTimeMs = SystemClock.elapsedRealtime(); // release previous request object to avoid leaking request object when mQueue is drained. request = null; try { // Take a request from the queue. // 1、从请求队列取出请求 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; } addTrafficStatsTag(request); // Perform the network request. // 2、进行网络请求,并返回 (调用 BasicNetwork.perfomRequest(...)) 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. // 3、将网络请求的回来的数据,转化成请求的所需要的数据格式 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. // 4、如果需要磁盘缓存,则放到磁盘缓存中 if (request.shouldCache() && response.cacheEntry != null) { mCache.put(request.getCacheKey(), response.cacheEntry); request.addMarker("network-cache-written"); } // Post the response back. request.markDelivered(); // 5、分发请求结果 mDelivery.postResponse(request, response); } catch (VolleyError volleyError) { volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs); parseAndDeliverNetworkError(request, volleyError); } catch (Exception e) { VolleyLog.e(e, "Unhandled exception %s", e.toString()); VolleyError volleyError = new VolleyError(e); volleyError.setNetworkTimeMs(SystemClock.elapsedRealtime() - startTimeMs); mDelivery.postError(request, volleyError); } } }流程图
5、HttpStack
一个接口,实现类需要实现执行一个 HTTP 请求
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError;实现类 HurlStack ,基于 HttpURLConnection
@Override public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError { String url = request.getUrl(); // 放置头文件 HashMap<String, String> map = new HashMap<String, String>(); map.putAll(request.getHeaders()); map.putAll(additionalHeaders); if (mUrlRewriter != null) { String rewritten = mUrlRewriter.rewriteUrl(url); if (rewritten == null) { throw new IOException("URL blocked by rewriter: " + url); } url = rewritten; } URL parsedUrl = new URL(url); // 设置链接 HttpURLConnection connection = openConnection(parsedUrl, request); for (String headerName : map.keySet()) { connection.addRequestProperty(headerName, map.get(headerName)); } // 设置连接参数 setConnectionParametersForRequest(connection, request); // 设定 HTTP 协议版本 // Initialize HttpResponse with data from the HttpURLConnection. ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1); int responseCode = connection.getResponseCode(); if (responseCode == -1) { // -1 is returned by getResponseCode() if the response code could not be retrieved. // Signal to the caller that something was wrong with the connection. throw new IOException("Could not retrieve response code from HttpUrlConnection."); } StatusLine responseStatus = new BasicStatusLine(protocolVersion, connection.getResponseCode(), connection.getResponseMessage()); BasicHttpResponse response = new BasicHttpResponse(responseStatus); if (hasResponseBody(request.getMethod(), responseStatus.getStatusCode())) { // 将返回的数据设置到 response response.setEntity(entityFromConnection(connection)); } for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) { if (header.getKey() != null) { Header h = new BasicHeader(header.getKey(), header.getValue().get(0)); response.addHeader(h); } } return response; } /** * Initializes an {@link HttpEntity} from the given {@link HttpURLConnection}. * @param connection * @return an HttpEntity populated with data from <code>connection</code>. */ private static HttpEntity entityFromConnection(HttpURLConnection connection) { BasicHttpEntity entity = new BasicHttpEntity(); InputStream inputStream; try { // 获取数据流 inputStream = connection.getInputStream(); } catch (IOException ioe) { inputStream = connection.getErrorStream(); } entity.setContent(inputStream); entity.setContentLength(connection.getContentLength()); entity.setContentEncoding(connection.getContentEncoding()); entity.setContentType(connection.getContentType()); return entity; }
实现类 HttpClientStack, 基于 HttpClient
@Override public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError { // 创建一个 httpRequest 对象 HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders); // 添加文件头 addHeaders(httpRequest, additionalHeaders); addHeaders(httpRequest, request.getHeaders()); onPrepareRequest(httpRequest); // 空方法 // 参数 HttpParams httpParams = httpRequest.getParams(); int timeoutMs = request.getTimeoutMs(); // TODO: Reevaluate this connection timeout based on more wide-scale // data collection and possibly different for wifi vs. 3G. // 设置连接超时时间 HttpConnectionParams.setConnectionTimeout(httpParams, 5000); HttpConnectionParams.setSoTimeout(httpParams, timeoutMs); // 执行 HTTP 请求,并且返回 return mClient.execute(httpRequest); }
6、ResponseDelivery
接口,实现类是 ExecutorDelivery, 根据传进来 Handler 所在线程内分发结果
在调用 Volley.newRequestQueue(...) 的时候,会生成一个新的 RequestQueue 对象,同时生成一个传入主线程 Handler 的
ExecutorDelivery;
/** * 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 */ public RequestQueue(Cache cache, Network network, int threadPoolSize) { // ExecutorDelivery 负责分发结果, 传入一个主线程的 Handler 进去,是为了在主线程中分发结果 this(cache, network, threadPoolSize, new ExecutorDelivery(new Handler(Looper.getMainLooper()))); }
ExecutorDelivery 类
/** * Delivers responses and errors. */ public class ExecutorDelivery implements ResponseDelivery { /** Used for posting responses, typically to the main thread. */ // 用于 post 网络请求结果回调主线程 private final Executor mResponsePoster; /** * Creates a new response delivery interface. * @param handler {@link Handler} to post responses on */ public ExecutorDelivery(final Handler handler) { // Make an Executor that just wraps the handler. // 执行器用来包裹 handler mResponsePoster = new Executor() { @Override public void execute(Runnable command) { handler.post(command); } }; } /** * Creates a new response delivery interface, mockable version * for testing. * @param executor For running delivery tasks */ public ExecutorDelivery(Executor executor) { mResponsePoster = executor; } // 网络请求 NetworkDispatcher 的 run() 方法中,会调用 postResponse(...) 方法 @Override public void postResponse(Request<?> request, Response<?> response) { postResponse(request, response, null); } @Override public void postResponse(Request<?> request, Response<?> response, Runnable runnable) { request.markDelivered(); request.addMarker("post-response"); mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable)); } @Override public void postError(Request<?> request, VolleyError error) { request.addMarker("post-error"); Response<?> response = Response.error(error); mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, null)); } /** * A Runnable used for delivering network responses to a listener on the * main thread. * 用于分发网络请求结果到主线程的 listener */ @SuppressWarnings("rawtypes") private class ResponseDeliveryRunnable implements Runnable { private final Request mRequest; private final Response mResponse; private final Runnable mRunnable; public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) { mRequest = request; mResponse = response; mRunnable = runnable; } @SuppressWarnings("unchecked") @Override public void run() { // If this request has canceled, finish it and don't deliver. if (mRequest.isCanceled()) { mRequest.finish("canceled-at-delivery"); return; } // Deliver a normal response or error, depending. // 分发结果,会调用 Request 具体实现类中的 deliverResponse(...) 方法 if (mResponse.isSuccess()) { mRequest.deliverResponse(mResponse.result); } else { mRequest.deliverError(mResponse.error); } // If this is an intermediate response, add a marker, otherwise we're done // and the request can be finished. if (mResponse.intermediate) { mRequest.addMarker("intermediate-response"); } else { mRequest.finish("done"); } // If we have been provided a post-delivery runnable, run it. if (mRunnable != null) { mRunnable.run(); } } } }
将分发结果传递给 listener
@Override protected void deliverResponse(String response) { if (mListener != null) { mListener.onResponse(response); } }
网络请求结果分发流程图
说明:
(1)、NetworkDispatcher 中将网络请求的结果调用方法 ReponseDelivery.postResponse(...) 方法进行分发,这是在 workerThread中, ResponseDelivery 只是接口,最终还是会调用实现类 ExecutorDelivery.postResponse(...)
方法;
(2)、ExecutroDelivery.postResonse(...) 方法用 抱箍 handler 的 Executor 将 ResponseDeliveryRunnable 任务 post 回到主线程执行;
(3)、然后将网络请求结果传递给 listener;
7、Cache
接口,实现类是 DiskBasedCache, 磁盘缓存,默认是大小时 5M
8、RequestQueue
核心类
主要成员变量:
自动生成请求序列号
mSequenceGenerator = new AtomicInteger()
等待 Set
mWaitingRequests = new HashMap<String, Queue<Request<?>>>();
当前缓存的 Set
mCurrentRequests = new HashSet<Request<?>>();
缓存队列
PriorityBlockingQueue<Request<?>> mCacheQueue;
网络请求队列
PriorityBlockingQueue<Request<?>> mNetworkQueue;
网络
Network mNetwork;
分发结果
ResponseDelivery mDelivery;
网络线程
NetworkDispatcher[] mDispatchers;
磁盘缓存线程
CacheDispatcher mCacheDispatcher;
(1)、生成一个 RequestQueue 对象时,传入一个主线程的 Handler, 用于分发结果;
/** * 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 */ public RequestQueue(Cache cache, Network network, int threadPoolSize) { // ExecutorDelivery 负责分发结果, 传入一个主线程的 Handler 进去,是为了在主线程中分发结果 this(cache, network, threadPoolSize, new ExecutorDelivery(new Handler(Looper.getMainLooper()))); }
(2)、添加一个请求
/** * Adds a Request to the dispatch queue. * @param request The request to service * @return The passed-in request * 添加一个请求 */ public <T> Request<T> add(Request<T> request) { // Tag the request as belonging to this queue and add it to the set of current requests. request.setRequestQueue(this); synchronized (mCurrentRequests) { // 添加到当前缓存 set 中 mCurrentRequests.add(request); } // Process requests in the order they are added. // 设置 request 的序列号 request.setSequence(getSequenceNumber()); request.addMarker("add-to-queue"); // If the request is uncacheable, skip the cache queue and go straight to the network. // 是否需要缓存,默认是 true; 放入到网络请求队列中,并返回 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(); // 如果等待 Map 中已经有了 cacheKey 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; } }
(3)、调用 RequestQueue 的 start() 方法,会启动一个磁盘缓存线程和四个网络请求线程
/** * Starts the dispatchers in this queue. * 核心的开始 */ public void start() { stop(); // Make sure any currently running dispatchers are stopped. // Create the cache dispatcher and start it. // 创建磁盘缓存 dispatcher, 并启动 mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery); mCacheDispatcher.start(); // 会调用 CacheDispatcher.run() 方法 // Create network dispatchers (and corresponding threads) up to the pool size. // 启动网络 dispatchers for (int i = 0; i < mDispatchers.length; i++) { // 默认为四个 NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, mCache, mDelivery); mDispatchers[i] = networkDispatcher; networkDispatcher.start(); // 会调用 NetworkDispatcher.run() 方法 } }
9、Volley
对外提供 API, 并且启动请求队列 RequestQueue
/** 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. * You may set a maximum size of the disk cache in bytes. * * @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. * @param maxDiskCacheBytes the maximum size of the disk cache, in bytes. Use -1 for default size. * @return A started {@link RequestQueue} instance. */ public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) { // 创建缓存文件 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) { } if (stack == null) { // 如果版本大于等于 9 使用 HurlStack, 否则使用 HttpClientStack. // HurlStack 是用 HttpURLConnection, HttpClientStack 用的是 HttpClient 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)); } } // 网络请求, 实现类是 BasicNetwork Network network = new BasicNetwork(stack); RequestQueue queue; // RequestQueue 是核心 if (maxDiskCacheBytes <= -1){ // No maximum size specified // 没有指定磁盘缓存大小时, 使用默认 5M queue = new RequestQueue(new DiskBasedCache(cacheDir), network); }else{ // Disk cache size specified // 指定磁盘缓存大小时 queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network); } // 请求队列,队列默认启动四个网络线程请求 queue.start(); return queue; }
三、使用例子
已 StringRequest 为例
// Instantiate the RequestQueue. // 实例化 RequestQueue,里面会启动请求队列 RequestQueue queue = Volley.newRequestQueue(this); String url ="http://www.baidu.com"; // Request a string response from the provided URL. // 生成一个新的 Request 对象 StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse(String response) { // 返回结果 Log.i("volley", "response " + response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // 返回错误 } }); // Add the request to the RequestQueue. // 添加到请求队列 queue.add(stringRequest); }
分析完成。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories