Volley源码解析

来源:互联网 发布:不用手机注册淘宝账号 编辑:程序博客网 时间:2024/06/06 12:44

从newRequestQueue进行入手来进行一步步分析源码的流程

 public static RequestQueue newRequestQueue(Context context) {        return newRequestQueue(context, null);    } public static RequestQueue newRequestQueue(Context context, HttpStack stack){    return newRequestQueue(context, stack, -1);}

我们可以查看出来,它进行重载了两个方法来进行使用,最后的方法是下面这个

public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) {        //参数一:缓存到手机内置内存中        //参数二:通过查看我们可以发现,这个文件夹的名字是volley        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) {            if (Build.VERSION.SDK_INT >= 9) {                //HttpUrlConnection中的stack                stack = new HurlStack();            } else {                //HttpClient中的HttpClientStack                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);        }        else        {            // Disk cache size specified            queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network);        }        queue.start();        return queue;    }

通过上面的代码我们可以看出来,它会判断当前的sdk的大小,如果当前的sdk>=9,它会调用HurlStack(),否则,它会调用HttpClientStack这个方法

1.HurlStack 与 HttpClientStack 区别

由此可见,在Android 2.2 中HttpClient拥有较少的bug,所以使用它比较合适,在Android 2.3以后HttpUrlConnection是最佳的选择。它的api简单,体积比较小,因此非常试用于Android项目。压缩和缓存机制可以有效的减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。对于新的应用程序应该更加偏向于使用HttpURLConnection,因为在以后的工作当中我们也会将更多的时间放在优化HttpURLConnection上面。

  1. HurlStack中的父类的源码进行分析

    /**  * An HTTP stack abstraction.  * 抽象的http栈  */  public interface HttpStack {      /**      * Performs an HTTP request with the given parameters.      * 根据参数,执行http请求      * <p>A GET request is sent if request.getPostBody() == null. A POST request is sent otherwise,      * and the Content-Type header is set to request.getPostBodyContentType().</p>      *      * @param request the request to perform      * @param additionalHeaders additional headers to be sent together with      *         {@link Request#getHeaders()}      * @return the HTTP response      */      public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)          throws IOException, AuthFailureError;  }  

该父类主要规定了,子类必须有一个根据request请求数据,并且返回HttpResponse类的方法

OK,接下来我们先看HurlStack,这个类使用的是HttpURLConnection作为连接方式,在sdk较高版本推荐使用(其实目前市场上2.3的系统已经很少见了)
我们直接看这个类的核心方法performRequest()

@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);//设置请求方式      // Initialize HttpResponse with data from the HttpURLConnection.      ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);//http协议      int responseCode = connection.getResponseCode();//获取响应状态      if (responseCode == -1) {//-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);      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;  }  

整个方法分成几个步骤,首先是将请求参数,存储到map当中

HashMap<String, String> map = new HashMap<String, String>();         map.putAll(request.getHeaders());         map.putAll(additionalHeaders); 

然后是开启url连接

URL parsedUrl = new URL(url);  HttpURLConnection connection = openConnection(parsedUrl, request);//开启连接  

来看openConnection()方法

/**  * Opens an {@link HttpURLConnection} with parameters.  * 开启网络连接  * @param url  * @return an open connection  * @throws IOException  */  private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException {      HttpURLConnection connection = createConnection(url);      int timeoutMs = request.getTimeoutMs();      connection.setConnectTimeout(timeoutMs);      connection.setReadTimeout(timeoutMs);      connection.setUseCaches(false);      connection.setDoInput(true);      // use caller-provided custom SslSocketFactory, if any, for HTTPS      if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {//https          ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);      }      return connection;  }   /**  * Create an {@link HttpURLConnection} for the specified {@code url}.  */  protected HttpURLConnection createConnection(URL url) throws IOException {      return (HttpURLConnection) url.openConnection();  }  

这个方法主要就是调用url.openConnevtion()从而返回一个HttpURLConnection对象,其中的一些超时设置,是由request本身提供的
另外还根据url是否带有https,为HttpURLConnection设置setSSLSocketFactory(mSslSocketFactory对象是在构造方法中传入的)
得到HttpURLConnection,就设置请求参数

for (String headerName : map.keySet()) {//添加请求参数              connection.addRequestProperty(headerName, map.get(headerName));          } 

然后是确定请求方式(GET,POST还是别的)

setConnectionParametersForRequest(connection, request);//设置请求方式  

setConnectionParametersForRequest方法:

@SuppressWarnings("deprecation")      /**      * 设置请求方式      * @param connection      * @param request      * @throws IOException      * @throws AuthFailureError      */      /* package */       static void setConnectionParametersForRequest(HttpURLConnection connection,              Request<?> request) throws IOException, AuthFailureError {          switch (request.getMethod()) {              case Method.DEPRECATED_GET_OR_POST:                  // This is the deprecated way that needs to be handled for backwards compatibility.                  // If the request's post body is null, then the assumption is that the request is                  // GET.  Otherwise, it is assumed that the request is a POST.                  byte[] postBody = request.getPostBody();                  if (postBody != null) {                      // Prepare output. There is no need to set Content-Length explicitly,                      // since this is handled by HttpURLConnection using the size of the prepared                      // output stream.                      connection.setDoOutput(true);                      connection.setRequestMethod("POST");                      connection.addRequestProperty(HEADER_CONTENT_TYPE,                              request.getPostBodyContentType());                      DataOutputStream out = new DataOutputStream(connection.getOutputStream());                      out.write(postBody);                      out.close();                  }                  break;              case Method.GET:                  // Not necessary to set the request method because connection defaults to GET but                  // being explicit here.                  connection.setRequestMethod("GET");                  break;              case Method.DELETE:                  connection.setRequestMethod("DELETE");                  break;              case Method.POST:                  connection.setRequestMethod("POST");                  addBodyIfExists(connection, request);                  break;              case Method.PUT:                  connection.setRequestMethod("PUT");                  addBodyIfExists(connection, request);                  break;              case Method.HEAD:                  connection.setRequestMethod("HEAD");                  break;              case Method.OPTIONS:                  connection.setRequestMethod("OPTIONS");                  break;              case Method.TRACE:                  connection.setRequestMethod("TRACE");                  break;              case Method.PATCH:                  connection.setRequestMethod("PATCH");                  addBodyIfExists(connection, request);                  break;              default:                  throw new IllegalStateException("Unknown method type.");          }      }  

最后获取响应,将响应头信息包装成StatusLine对象,再包装成BasicHttpResponse对象

StatusLine responseStatus = new BasicStatusLine(protocolVersion,                  connection.getResponseCode(), connection.getResponseMessage());//响应状态类          BasicHttpResponse response = new BasicHttpResponse(responseStatus);  

然后为BasicHttpResponse加入响应内容

response.setEntity(entityFromConnection(connection));//解析响应实体  

entityFromConnection(HttpURLConnection connection)方法:

/**      * Initializes an {@link HttpEntity} from the given {@link HttpURLConnection}.      * <br>解析出响应实体      * @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;      }  

最后,加入响应头部内容

 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);              }          }  

OK,这样就返回了一个具有完整信息的HttpResponse对象。整个过程比较简单,是常规的网络请求内容。

2.HttpClientStack的实现,直接来看performRequest()方法

@Override  public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)          throws IOException, AuthFailureError {      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);      return mClient.execute(httpRequest);  }  

请求步骤,首先是根据请求方式,构造HttpUriRequest对象,并且设置请求参数

HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders); 

createHttpRequest()方法:

/**  * Creates the appropriate subclass of HttpUriRequest for passed in request.  * 根据请求方式返回对应HttpUriRequest的子类  */  @SuppressWarnings("deprecation")  /* protected */   static HttpUriRequest createHttpRequest(Request<?> request,          Map<String, String> additionalHeaders) throws AuthFailureError {      switch (request.getMethod()) {          case Method.DEPRECATED_GET_OR_POST: {              // This is the deprecated way that needs to be handled for backwards compatibility.              // If the request's post body is null, then the assumption is that the request is              // GET.  Otherwise, it is assumed that the request is a POST.              byte[] postBody = request.getPostBody();              if (postBody != null) {                  HttpPost postRequest = new HttpPost(request.getUrl());                  postRequest.addHeader(HEADER_CONTENT_TYPE, request.getPostBodyContentType());                  HttpEntity entity;                  entity = new ByteArrayEntity(postBody);                  postRequest.setEntity(entity);                  return postRequest;              } else {                  return new HttpGet(request.getUrl());              }          }          case Method.GET:              return new HttpGet(request.getUrl());          case Method.DELETE:              return new HttpDelete(request.getUrl());          case Method.POST: {              HttpPost postRequest = new HttpPost(request.getUrl());              postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());              setEntityIfNonEmptyBody(postRequest, request);//设置请求参数              return postRequest;          }          case Method.PUT: {              HttpPut putRequest = new HttpPut(request.getUrl());              putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());              setEntityIfNonEmptyBody(putRequest, request);              return putRequest;          }          case Method.HEAD:              return new HttpHead(request.getUrl());          case Method.OPTIONS:              return new HttpOptions(request.getUrl());          case Method.TRACE:              return new HttpTrace(request.getUrl());          case Method.PATCH: {              HttpPatch patchRequest = new HttpPatch(request.getUrl());              patchRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());              setEntityIfNonEmptyBody(patchRequest, request);              return patchRequest;          }          default:              throw new IllegalStateException("Unknown request method.");      }  }  

从createHttpRequest()方法可以看出,在HttpClient中,只要根据请求方式,new一个HttpGet/HttpPost/….对象就可以了(而urlstack这一步是真的connnection而言的)
接着是为HttpUriRequest对象设置请求头部

   addHeaders(httpRequest, additionalHeaders);//添加缓存头     addHeaders(httpRequest, request.getHeaders());//添加请求头  

addHeaders方法:

/**  * 添加响应头  * @param httpRequest  * @param headers  */  private static void addHeaders(HttpUriRequest httpRequest, Map<String, String> headers) {      for (String key : headers.keySet()) {          httpRequest.setHeader(key, headers.get(key));      }  }  

最后,将HttpUriRequest对象交给httpClient执行

return mClient.execute(httpRequest);  

3.HurlStack与HttpClientStack区别进行总结

OK,HttpClientStack比我们想象的还要简单,起码比HurlStack简单,这是当然的,因为使用httpClient方式,其本质就是对urlConnection的封装,然而这个封装并不是很完美,所以造成了版本之间的差异。

2. new RequestQueue(new DiskBasedCache(cacheDir), network)这里面的源码进行分析

我们点击跳转到这个构造方法中

//参数一:缓存 参数二:联网工作的状态public RequestQueue(Cache cache, Network network) {    this(cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE);}当点击里面的那个this方法时候会跳转到如下构造函数中  public RequestQueue(Cache cache, Network network, int threadPoolSize) {    this(cache, network, threadPoolSize,            new ExecutorDelivery(new Handler(Looper.getMainLooper())));}

通过分析我们可以发现,最后是将网络请求响应的数据发送到主线程进行操作的

3.queue.start(); 这个里面的方法中进行分析
   public void start() {        //确保当前正在运行的调度程序已经停止        stop();          //参数一:实例化缓存分流队列        //参数二:实际化到达网络的请求队列        //参数三:用于检索和存储响应的高速缓存接口        //参数四:响应传递机制        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();        }    }

CacheDispatcher是缓存调度线程,在调用start()方法。在循环中调用了NetworkDispatcher网络调度线程。默认情况下网络调度线程是4,缓存调度线程是一个,一共5个线程在后台运行并等待请求的到来。同时进行添加到请求到队列里面来。

接下来我们一起来看一下add()方法的源码进行分析

 public <T> Request<T> add(Request<T> request) {        // 将此请求与指定的队列进行关联,当这个请求队列被通知        request.setRequestQueue(this);        synchronized (mCurrentRequests) {            mCurrentRequests.add(request);        }        // 按照添加的顺序处理请求        request.setSequence(getSequenceNumber());        request.addMarker("add-to-queue");        // 如果不能缓存,将请求添加到网络请求队列中        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();            //如果此前有相同的请求且还没有返回结果,就将次请求加入mWaitingRequests队列            if (mWaitingRequests.containsKey(cacheKey)) {                // 如果有已经在队列的请求,后面的进行等待                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;        }    }

代码分析:request.shouldCache()判断是否可以进行缓存的,默认是可以缓存的。如果不能缓存,则将请求添加到网络请求队列里面。如果能缓存,则判断之前是否有执行相同的请求且没有返回结果的,如果有的话将此请求加入到mWaitingRequests队列中,不再进行重复的请求,没有的话就请求加入到缓存的队列mCacheQueue.RequestQueue的add方法并没有请求网络或者对缓存的操作,当将请求添加到网络请求的队列或者缓存队列时,在后台的网络调度线程和缓存调度线程轮询各自的请求队列,若发现有请求任务则开始执行。

我们来看一下缓存调度线程CacheDispatcher

@Overridepublic 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;        try {            // 获取缓存队列中的一个请求            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 (request.isCanceled()) {                request.finish("cache-discard-canceled");                continue;            }            // 查看是否有缓存的响应            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 (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.            request.addMarker("cache-hit");            //对数据的解析并回调给主线程            Response<?> response = request.parseNetworkResponse(                    new NetworkResponse(entry.data, entry.responseHeaders));            request.addMarker("cache-hit-parsed");            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());        }    }}

分析:首先从缓存队列取出请求,判断请求是否取消,如果请求没有被取消则判断是否有缓存的响应,如果有缓存的响应。如果有缓存的响应并且没有过期,则对缓存响应进行解析并回调给主线程:如果没有缓存的响应,则将请求添加到网络调度线程

网络调度线程NetworkDispatcher

@Overridepublic 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 {            // 从队列中取出请求            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.            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.            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) {                mCache.put(request.getCacheKey(), response.cacheEntry);                request.addMarker("network-cache-written");            }            // Post the response back.            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);        }    }}

这个网络调度线程和缓存调度线程处理的逻辑几乎相同,在这里,不做过多的介绍了,mNetwork.performRequest(request);我们可以观察到这个里面是个接口,实现类是BasicNetwork,我们来接着往下进行分析

1.Network接口类代码如下
public interface Network {    /**     * Performs the specified request.执行这个请求     * @param request Request to process//待处理的请求     * @return A {@link NetworkResponse} with data and caching metadata; will never be null     * 返回一个请求结果,不会为空     * @throws VolleyError on errors     */    public NetworkResponse performRequest(Request<?> request) throws VolleyError;}
2.BasicNetwork中的performRequest里面的请求进行分析
 /** * @title performRequest执行各种Request请求并以NetworkResponse的形式返回结果 * @param Request * @return NetworkResponse * @throws VolleyError * 定义:{@link Network#performRequest(Request)} * 被调:{@link NetworkDispatcher#run()} *  */@Override//NetworkDispatcher的run()方法中调用public NetworkResponse performRequest(Request<?> request) throws VolleyError {    long requestStart = SystemClock.elapsedRealtime();//开始请求时间    while (true) {        HttpResponse httpResponse = null;//apache的请求结果        byte[] responseContents = null;//请求的内容        Map<String, String> responseHeaders = new HashMap<String, String>();//响应结果头部信息        try {            // Gather headers.            Map<String, String> headers = new HashMap<String, String>();//保存缓存数据            addCacheHeaders(headers, request.getCacheEntry());//先获取缓存数据            httpResponse = mHttpStack.performRequest(request, headers);//去调用mHttpStack的实现方法执行请求            StatusLine statusLine = httpResponse.getStatusLine();//获取http状态线            int statusCode = statusLine.getStatusCode();//获取状态码            responseHeaders = convertHeaders(httpResponse.getAllHeaders());            // Handle cache validation.//处理缓存验证            if (statusCode == HttpStatus.SC_NOT_MODIFIED) {//返回缓存数据                return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED,                        request.getCacheEntry().data, responseHeaders, true);            }            //把HttpEntity转化为byte[]数据            responseContents = entityToBytes(httpResponse.getEntity());            // if the request is slow, log it.//如果请求很慢,就打印出来看一下            long requestLifetime = SystemClock.elapsedRealtime() - requestStart;            logSlowRequests(requestLifetime, request, responseContents, statusLine);//打印            //连接正常但是返回无内容,抛出IO异常            if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_NO_CONTENT) {                throw new IOException();            }            return new NetworkResponse(statusCode, responseContents, responseHeaders, false);        } catch (SocketTimeoutException e) {//读取超时,重试            attemptRetryOnException("socket", request, new TimeoutError());        } catch (ConnectTimeoutException e) {//连接超时,重试            attemptRetryOnException("connection", request, new TimeoutError());        } catch (MalformedURLException e) {//Bad URL            throw new RuntimeException("Bad URL " + request.getUrl(), e);        } catch (IOException e) {//IO异常            int statusCode = 0;            NetworkResponse networkResponse = null;            if (httpResponse != null) {                statusCode = httpResponse.getStatusLine().getStatusCode();            } else {//如果没有返回httpResponse,就说明没连接                throw new NoConnectionError(e);            }            VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl());            if (responseContents != null) {//返回数据不为空                networkResponse = new NetworkResponse(statusCode, responseContents,                        responseHeaders, false);//创建响应体                if (statusCode == HttpStatus.SC_UNAUTHORIZED ||                        statusCode == HttpStatus.SC_FORBIDDEN) {//认证失败异常,重试                    attemptRetryOnException("auth",                            request, new AuthFailureError(networkResponse));                } else {//服务器异常                    // TODO: Only throw ServerError for 5xx status codes.                    throw new ServerError(networkResponse);//只有状态码为5XX才抛出服务器异常                }            } else {//网络异常                throw new NetworkError(networkResponse);            }        }    }}

代码解析:

1.先是通过mHttpStack把请求执行并且获取它的响应结果,根据HttpStatus做出各种判断。2.然后再把httpResponse的Entity转化为ByteArray,并处理各种发生的异常。3.最后的过程是这样的:通过Volley创建一个RequestQueue请求队列,当这个队列开始运作的时候会启动NetworkDispatcher这个工作线程,而BasicNetwork的performRequest()的方法就在NetworkDispatcher线程run()方法中调用,然后通过mHttpStack的performRequest()方法获取一个networkResponse,在NetworkDispatcher线程把这个networkResponse转化为期望的数据类型,比如Response<String>,Response<Json>,Response<Bitmap>。
3. mDelivery.postResponse(request, response);
@Overridepublic void postResponse(Request<?> request, Response<?> response, Runnable runnable) {    request.markDelivered();    request.addMarker("post-response");    mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable));}
4.ResponseDeliveryRunnable我们来看一下这里面都做了什么处理的
/** * 在主线程进行返回一个网络响应的交付线程 */@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 (mRequest.isCanceled()) {            mRequest.finish("canceled-at-delivery");            return;        }        // 如果响应错误就可以调用错误的方法传入错误信息        if (mResponse.isSuccess()) {            mRequest.deliverResponse(mResponse.result);        } else {            mRequest.deliverError(mResponse.error);        }        // 如果这是一个中间响应,添加一个标记,否则我们就完成了。        //请求可以完成        if (mResponse.intermediate) {            mRequest.addMarker("intermediate-response");        } else {            mRequest.finish("done");        }        // 如果提供了交付,我们进行请求它        if (mRunnable != null) {            mRunnable.run();        }   }}

Volley源码分析结束。