目源码的目录树:

创新互联公司专业为企业提供文山州网站建设、文山州做网站、文山州网站设计、文山州网站制作等企业网站建设、网页设计与制作、文山州企业网站模板建站服务,10年文山州做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。
- [Android]
 - ┗━[Volley]
 - ┣━AuthFailureError.java
 - ┣━Cache.java
 - ┣━CacheDispatcher.java
 - ┣━DefaultRetryPolicy.java
 - ┣━ExecutorDelivery.java
 - ┣━InternalUtils.java
 - ┣━Network.java
 - ┣━NetworkDispatcher.java
 - ┣━NetworkError.java
 - ┣━NetworkResponse.java
 - ┣━NoConnectionError.java
 - ┣━ParseError.java
 - ┣━RedirectError.java
 - ┣━Request.java
 - ┣━RequestQueue.java
 - ┣━Response.java
 - ┣━ResponseDelivery.java
 - ┣━RetryPolicy.java
 - ┣━ServerError.java
 - ┣━TimeoutError.java
 - ┣━[toolbox]
 - ┃ ┣━AndroidAuthenticator.java
 - ┃ ┣━Authenticator.java
 - ┃ ┣━BasicNetwork.java
 - ┃ ┣━ByteArrayPool.java
 - ┃ ┣━ClearCacheRequest.java
 - ┃ ┣━DiskBasedCache.java
 - ┃ ┣━httpClientStack.java
 - ┃ ┣━HttpHeaderParser.java
 - ┃ ┣━HttpStack.java
 - ┃ ┣━HurlStack.java
 - ┃ ┣━ImageLoader.java
 - ┃ ┣━ImageRequest.java
 - ┃ ┣━JsonArrayRequest.java
 - ┃ ┣━JsonObjectRequest.java
 - ┃ ┣━JsonRequest.java
 - ┃ ┣━NetworkImageView.java
 - ┃ ┣━NoCache.java
 - ┃ ┣━PoolingByteArrayOutputStream.java
 - ┃ ┣━RequestFuture.java
 - ┃ ┣━StringRequest.java
 - ┃ ┗━Volley.java
 - ┣━VolleyError.java
 - ┗━VolleyLog.java
 
可以看出,Volley源码放置得较为杂乱,不同功能模块的类并没有归到不同的包中。相比之下UIL的源码结构较为规范和合理。
从常用case入手,推断其项目架构
官网上给出的最简单的使用例子如下所示:
final TextView mTextView = (TextView) findViewById(R.id.text);
- // 1. 新建一个Queue
 - RequestQueue queue = Volley.newRequestQueue(this);
 - String url ="http://www.google.com";
 - // 2. 新建一个Request,写好listener
 - StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
 - new Response.Listener
 () { - @Override
 - public void onResponse(String response) {
 - // Display the first 500 characters of the response string.
 - mTextView.setText("Response is: "+ response.substring(0,500));
 - }
 - }, new Response.ErrorListener() {
 - @Override
 - public void onErrorResponse(VolleyError error) {
 - mTextView.setText("That didn't work!");
 - }
 - });
 - // 3. 将Request放到Queue里面执行
 - queue.add(stringRequest);
 - 结合下面这张图:
 - 架构图
 - 我们可以大致了解Volley的使用方法(见注释)和内部结构。下面就这个usecase展开进行源码级别的简述。
 - Volley类
 - Volley类提供了4个静态方法来方便用户新建Queue。其中:
 - public static RequestQueue newRequestQueue(Context context) {
 - return newRequestQueue(context, null);
 - }
 - 一句最终会调用:
 - // 传入 context,stack=null,maxDiskCacheBytes=-1
 - public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) {
 - File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
 - String userAgent = "volley/0"; //1. 设置userAgent
 - try {
 - String packageName = context.getPackageName();
 - PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
 - userAgent = packageName + "/" + info.versionCode;
 - } catch (NameNotFoundException e) {
 - }
 - if (stack == null) {
 - if (Build.VERSION.SDK_INT >= 9) { //2. 选择用哪个httpclient
 - 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;
 - if (maxDiskCacheBytes <= -1)
 - {
 - // No maximum size specified
 - queue = new RequestQueue(new DiskBasedCache(cacheDir), network); //3. 新建Queue
 - }
 - else
 - {
 - // Disk cache size specified
 - queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network);
 - }
 - queue.start();// 4. 传入Queue
 - return queue;
 - }
 
值得注意的是:
Volley会根据SDK的version来决定使用java.net.HttpURLConnection(Build.VERSION.SDK_INT >= 9)还是org.apache.http.client.HttpClient
新建Queue后,Queue马上会被start。
- stack类负责发送request(com.android.volley.Request)和获取response(org.apache.http.HttpResponse),network类负责分析和处理response,包装成NetworkResponse(com.android.volley.NetworkResponse)。
 - 我们首先忽略掉network相关的细节,看一下queue的实现和request的调度策略。
 - RequestQueue
 - 先来看一下RequestQueue的构造方法:
 - 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())));
 - }
 - 这里出现了一个新面孔ExecutorDelivery,根据字面意思可以猜测它是负责将请求的结果分发到主线程上,或者在主线程上执行回调(listener)。继续调用:
 - public RequestQueue(Cache cache, Network network, int threadPoolSize,
 - ResponseDelivery delivery) {
 - mCache = cache;
 - mNetwork = network;
 - mDispatchers = new NetworkDispatcher[threadPoolSize];
 - mDelivery = delivery;
 - }
 
这里又出现了一个新面孔NetworkDispatcher。留意到threadPoolSize这个数组长度参数的字面意义,结合上面的Volley架构图,猜想NetworkDispatcher是一个work thread,循环等待并通过network执行在Queue上的request。
RequestQueue被实例化后,便调用其start()方法:
- public void 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();
 - }
 - }
 - 相应地有:
 - public void stop() {
 - if (mCacheDispatcher != null) {
 - mCacheDispatcher.quit();
 - }
 - for (int i = 0; i < mDispatchers.length; i++) {
 - if (mDispatchers[i] != null) {
 - mDispatchers[i].quit();
 - }
 - }
 - }
 
这里的逻辑很简单:
开始之前停止所有旧的任务(即interrupt所有worker thread)。
启动一个负责cache的worker thread。
启动n个负责network的worker thread。
worker thread开始不断地等待来自Queue的request。
Request
接下来执行queue.add(stringRequest); ,一个request被加入到queue中,代码如下所示:
- 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"); // marker用来指示request当前的状态,实际上是用来打log
 - // 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
 > stagedRequests = mWaitingRequests.get(cacheKey); - if (stagedRequests == null) {
 - stagedRequests = new LinkedList
 >(); - }
 - 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;
 - }
 - }
 
这里的逻辑是:
对新加进来的request进行一些设置。
如果不需要cache,那么把request直接加到network queue中。
根据key检查request是否正在执行。如果是,则将其放入到waiting链表中。猜想当request完成的时候会调用某个方法将key在waiting链表中删除,然后依次执行waiting的request。如果否,则将其加入cache queue中。
CacheDispatcher
假设该uri访问是***次执行,那么对应的request会被放到cache queue中。cache worker thread(cache dispatcher)发现cache queue中存在request,会马上将其dequeue并执行。我们来看一下CacheDispatcher的run方法:
- public class CacheDispatcher extends Thread {
 - private final Cache mCache; // 一开始传入了“new DiskBasedCache(cacheDir)”
 - ...
 - public void quit() {
 - mQuit = true;
 - interrupt();
 - }
 - @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();
 - Request> request;
 - while (true) {
 - // release previous request object to avoid leaking request object when mQueue is drained.
 - request = null; //确保***一个request做完后能及时回收内存。
 - try {
 - // Take a request from the queue.
 - 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;
 - }
 - // miss cache则直接将request放到network queue中
 - 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;
 - }
 - // cache 过期了,直接将request放到network queue中
 - if (entry.isExpired()) {
 - request.addMarker("cache-hit-expired");
 - request.setCacheEntry(entry);
 - mNetworkQueue.put(request);
 - continue;
 - }
 - // 将cache中的data包装成一个response
 - request.addMarker("cache-hit");
 - Response> response = request.parseNetworkResponse(
 - new NetworkResponse(entry.data, entry.responseHeaders));
 - request.addMarker("cache-hit-parsed");
 - if (!entry.refreshNeeded()) {
 - // cache不需要刷新,直接将response交给delivery
 - mDelivery.postResponse(request, response);
 - } else {
 - // cache需要刷新。现将旧的内容返回,同时将request放进network queue。
 - 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());
 - }
 - }
 - }
 - }
 
接下来看一下mDelivery.postResponse这个方法。
ExecutorDelivery
从上文得知,mDelivery是一个ExecutorDelivery的实例(在新建RequestQueue时传入)。
ExecutorDelivery的初始化代码如下所示:
- public ExecutorDelivery(final Handler handler) {
 - // Make an Executor that just wraps the handler.
 - mResponsePoster = new Executor() { // java.util.concurrent.Executor;
 - @Override
 - public void execute(Runnable command) {
 - handler.post(command);
 - }
 - };
 - }
 
关于java.util.concurrent.Executor可以看这篇文章,这里就不展开了。
postResponse代码如下所示:
- @Override
 - public void postResponse(Request> request, Response> response, Runnable runnable) {
 - request.markDelivered(); //标记为已分发
 - request.addMarker("post-response");
 - mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable)); // 在初始化时传入的handler中执行ResponseDeliveryRunnable
 - }
 - ResponseDeliveryRunnable是ExecutorDelivery的一个子类,负责根据request的不同结果调用对应的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"); // 会调用 RequestQueue的finish方法
 - return;
 - }
 - // Deliver a normal response or error, depending.
 - if (mResponse.isSuccess()) {
 - mRequest.deliverResponse(mResponse.result); //调用 listener的onResponse(response)
 - } 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();
 - }
 - }
 - }
 
接下来我们回头看看NetworkDispatcher对network queue的处理。
NetworkDispatcher
NetworkDispatcher的源码如下所示:
- public class NetworkDispatcher extends Thread {
 - private final Network mNetwork; // BasicNetwork实例
 - ...
 - private final BlockingQueue
 > mQueue; // network queue - ...
 - public void quit() {
 - mQuit = true;
 - interrupt();
 - }
 - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
 - private void addTrafficStatsTag(Request> request) { // 方便统计Volley的网络流量
 - ...
 - }
 - @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 {
 - //1. 堵塞读取network queue中的request
 - 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);
 - //2. 在network对象中堵塞执行request
 - 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()) { // 304表示资源未被修改
 - request.finish("not-modified");
 - continue;
 - }
 - //3. 将NetworkResponse转成Response
 - 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.
 - if (request.shouldCache() && response.cacheEntry != null) {
 - // 4. Response放到cache中
 - mCache.put(request.getCacheKey(), response.cacheEntry);
 - request.addMarker("network-cache-written");
 - }
 - //5. 通过Delivery回调结果
 - request.markDelivered();
 - 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);
 - }
 - }
 - }
 - private void parseAndDeliverNetworkError(Request> request, VolleyError error) {
 - error = request.parseNetworkError(error);
 - mDelivery.postError(request, error);
 - }
 - }
 
NetworkDispatcher的处理流程和CacheDispatcher差不多,见注释。TrafficStats的介绍可以看这里。
上述代码的关键在于mNetwork.performRequest(request)和request.parseNetworkResponse(networkResponse)这两个调用。
- Network
 - Network是一个接口,只有一个performRequest(Request> request)方法:
 - public interface Network {
 - public NetworkResponse performRequest(Request> request) throws VolleyError;
 - }
 
本文例子中Network的实现类是BasicNetwork:
- public class BasicNetwork implements Network {
 - protected static final boolean DEBUG = VolleyLog.DEBUG;
 - private static int SLOW_REQUEST_THRESHOLD_MS = 3000;
 - 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));
 - }
 - ...
 - }
 - 注意到BasicNetwork的两个关键的成员:mHttpStack和mPool,和对apache依赖:
 - import org.apache.http.Header;
 - import org.apache.http.HttpEntity;
 - import org.apache.http.HttpResponse;
 - import org.apache.http.HttpStatus;
 - import org.apache.http.StatusLine;
 
可我们先来看一下performRequest()的执行流程:
- public NetworkResponse performRequest(Request> request) throws VolleyError {
 - long requestStart = SystemClock.elapsedRealtime();
 - while (true) {
 - // 依赖 org.apache.http.HttpResponse
 - HttpResponse httpResponse = null;
 - byte[] responseContents = null;
 - Map
 responseHeaders = Collections.emptyMap(); - try {
 - // 1. 生成header
 - Map
 headers = new HashMap (); - addCacheHeaders(headers, request.getCacheEntry());
 - // 2. 通过httpstack发起请求。注意‘发起请求’这个动作不在request中进行,request只是保存着请求的信息。
 - httpResponse = mHttpStack.performRequest(request, headers);
 - // 3. 获得请求结果的一些信息
 - StatusLine statusLine = httpResponse.getStatusLine();
 - int statusCode = statusLine.getStatusCode();
 - responseHeaders = convertHeaders(httpResponse.getAllHeaders());
 - // 4. 通过statusCode(304)来判断是否可以直接使用cache
 - 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);
 - }
 - // 从cache中取出data,返回新的NetworkResponse
 - entry.responseHeaders.putAll(responseHeaders);
 - return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data,
 - entry.responseHeaders, true,
 - SystemClock.elapsedRealtime() - requestStart);
 - }
 - // 5. 通过statusCode通过判断是否需要重定向
 - if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
 - String newUrl = responseHeaders.get("Location");
 - request.setRedirectUrl(newUrl);
 - }
 - // 6. 取出reponse中的data,为字节数组
 - // Some responses such as 204s do not have content. We must check.
 - if (httpResponse.getEntity() != null) {
 - // 通过entityToBytes从outputstream中读取数据,throws IOException
 - 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);
 - } catch (SocketTimeoutException e) {
 - attemptRetryOnException("socket", request, new TimeoutError());
 - } catch (ConnectTimeoutException e) {
 - attemptRetryOnException("connection", request, new TimeoutError());
 - } catch (MalformedURLException e) {
 - throw new RuntimeException("Bad URL " + request.getUrl(), e);
 - } catch (IOException e) {
 - // 7. 如果entityToBytes方法throw了IOException
 - int statusCode = 0;
 - NetworkResponse networkResponse = null;
 - if (httpResponse != null) {
 - statusCode = httpResponse.getStatusLine().getStatusCode();
 - } else {
 - throw new NoConnectionError(e);
 - }
 - if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY ||
 - statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
 - VolleyLog.e("Request at %s has been redirected to %s", request.getOriginUrl(), request.getUrl());
 - } else {
 - VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());
 - }
 - // 如果reponseContent有数据
 - if (responseContents != null) {
 - networkResponse = new NetworkResponse(statusCode, responseContents,
 - responseHeaders, false, SystemClock.elapsedRealtime() - requestStart);
 - // 那么根据statusCode执行重试
 - if (statusCode == HttpStatus.SC_UNAUTHORIZED ||
 - statusCode == HttpStatus.SC_FORBIDDEN) {
 - attemptRetryOnException("auth",
 - request, new AuthFailureError(networkResponse));
 - } else if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY ||
 - statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
 - attemptRetryOnException("redirect",
 - request, new RedirectError(networkResponse));
 - } else {
 - // TODO: Only throw ServerError for 5xx status codes.
 - throw new ServerError(networkResponse);
 - }
 - } else {
 - throw new NetworkError(e);
 - }
 - }
 - }
 - }
 
attemptRetryOnException()代码如下所示:
- private static void attemptRetryOnException(String logPrefix, Request> request,
 - VolleyError exception) throws VolleyError {
 - RetryPolicy retryPolicy = request.getRetryPolicy();
 - int oldTimeout = request.getTimeoutMs();
 
- try {
 - // 关键语句
 - retryPolicy.retry(exception);
 - } catch (VolleyError e) {
 - request.addMarker(
 - String.format("%s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout));
 - throw e;
 - }
 - request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, oldTimeout));
 - }
 
RetryPolicy是一个接口:
- public interface RetryPolicy {
 - public int getCurrentTimeout();
 - public int getCurrentRetryCount();
 - public void retry(VolleyError error) throws VolleyError;
 - }
 
如没有特殊指定,request中的RetryPolicy为DefaultRetryPolicy,其retry方法实现如下:
- public void retry(VolleyError error) throws VolleyError {
 - mCurrentRetryCount++;
 - mCurrentTimeoutMs += (mCurrentTimeoutMs * mBackoffMultiplier);
 - if (!hasAttemptRemaining()) {
 - throw error;
 - }
 - }
 
如果还没超出重试次数上限,那么不会抛出异常,并返回到performRequest()的while循环中。接下来分析一下BaseNetwork的entityToBytes()方法:
- private byte[] entityToBytes(HttpEntity entity) throws IOException, ServerError {
 - // 1. 新建PoolingByteArrayOutputStream
 - PoolingByteArrayOutputStream bytes =
 - new PoolingByteArrayOutputStream(mPool, (int) entity.getContentLength());
 - byte[] buffer = null;
 - try {
 - InputStream in = entity.getContent();
 - if (in == null) {
 - throw new ServerError();
 - }
 
- // 2. 在字节池中取出1024字节buffer
 - buffer = mPool.getBuf(1024);
 - int count;
 - // 3. 从entity的inputStream中读出数据到buffer
 - while ((count = in.read(buffer)) != -1) {
 - // 将buffer写到PoolingByteArrayOutputStream中
 - bytes.write(buffer, 0, count);
 - }
 - // 4. 将所有数据返回
 - return bytes.toByteArray();
 - } finally&n
 标题名称:Android Volley库源码简析(HTTP Request部分)
转载来源:http://www.csdahua.cn/qtweb/news20/42820.html网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网