Android中关于Volley的使用(九)认识HurlStack(HttpClientStack)

来源:互联网 发布:淘宝上罂粟壳叫什么 编辑:程序博客网 时间:2024/05/16 10:22

在Volley类中创建RequestQueue的时候,Volley就会根据设备的SDK版本来创建不同的HttpStack接口实现类,分别是HurlStack和HttpClientStack。

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. if (stack == null) {  
  2.     if (Build.VERSION.SDK_INT >= 9) {  
  3.         stack = new HurlStack();  
  4.     } else {  
  5.         stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));  
  6.     }  
  7. }  

而在前面的章节中讲到,在BasicNetwork中,其实真正去跟网络打交道的正是这两个对象,在BasicNetwork, 调用HttpStack的performRequest方法,

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public NetworkResponse performRequest(Request<?> request) throws VolleyError {  
  2.     ...  
  3.     httpResponse = mHttpStack.performRequest(request, headers);  


由于HurlStack和HttpClientStack的实现机制是一样的,只是使用的类不一样,我们这篇文章就只讲解HurlStack了。

下面是HurlStack中performRequest方法,
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)  
  2.         throws IOException, AuthFailureError {  
  3.     String url = request.getUrl();  
  4.     HashMap<String, String> map = new HashMap<String, String>();  
  5.     map.putAll(request.getHeaders());//默认为null  
  6.     map.putAll(additionalHeaders);//添加头部,主要是缓存相关的头部信息  
  7.     if (mUrlRewriter != null) {  
  8.         ...//代码不执行  
  9.     }  
  10.     URL parsedUrl = new URL(url);  
  11.     HttpURLConnection connection = openConnection(parsedUrl, request);//打开Connection  
  12.     for (String headerName : map.keySet()) {  
  13.         connection.addRequestProperty(headerName, map.get(headerName));  
  14.     }//将Map的对象添加到Connection的属性中  
  15.     setConnectionParametersForRequest(connection, request);//设置connection方法,主要是设置Method属性和Content(for post/put)  
  16.     // Initialize HttpResponse with data from the HttpURLConnection.  
  17.     ProtocolVersion protocolVersion = new ProtocolVersion("HTTP"11);//Http 1.1 协议  
  18.     int responseCode = connection.getResponseCode();  
  19.     if (responseCode == -1) {  
  20.         // -1 is returned by getResponseCode() if the response code could not be retrieved.  
  21.         // Signal to the caller that something was wrong with the connection.  
  22.         throw new IOException("Could not retrieve response code from HttpUrlConnection.");  
  23.     }  
  24.     StatusLine responseStatus = new BasicStatusLine(protocolVersion,  
  25.             connection.getResponseCode(), connection.getResponseMessage());  
  26.     BasicHttpResponse response = new BasicHttpResponse(responseStatus);  
  27.     response.setEntity(entityFromConnection(connection));将返回的内容解析成response的Entity对象  
  28.     for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {  
  29.         if (header.getKey() != null) {  
  30.             Header h = new BasicHeader(header.getKey(), header.getValue().get(0));  
  31.             response.addHeader(h);  
  32.         }  
  33.     }  
  34.     return response;  
  35. }  
HttpURLConnection是Android3.0以后才提供的一个网络访问类,而HurlStack类,也正是H(ttp)URL的缩写,所以这个类,其实就是基于HttpUrlConnection的实现,其步骤如下:
1)从Request中获得url参数,根据url参数构造URL对象,而URL对象是java提供的获取网络资源的一个封装好的实用类。
2)从URL对象打开Connection,并设置connection的超时,缓存,让网络资源写入等属性。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException {  
  2.     HttpURLConnection connection = createConnection(url);  
  3.   
  4.     int timeoutMs = request.getTimeoutMs();  
  5.     connection.setConnectTimeout(timeoutMs);  
  6.     connection.setReadTimeout(timeoutMs);  
  7.     connection.setUseCaches(false);  
  8.     connection.setDoInput(true);  
  9.   
  10.     // use caller-provided custom SslSocketFactory, if any, for HTTPS  
  11.     if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {  
  12.         ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);  
  13.     }  
  14.   
  15.     return connection;  
  16. }  
3)调用方法 setConnectionParametersForRequest 来设置 Method属性,如果是Post或者Put的话,还要设置Content内容。
4)设置Http 协议,这里基本上是1.1了。
5)获得Response的流,并将其解析成对应的HttpEntity对象,设置给Response.entity字段,返回给BasicNetwork。
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private static HttpEntity entityFromConnection(HttpURLConnection connection) {  
  2.     BasicHttpEntity entity = new BasicHttpEntity();  
  3.     InputStream inputStream;  
  4.     try {  
  5.         inputStream = connection.getInputStream();  
  6.     } catch (IOException ioe) {  
  7.         inputStream = connection.getErrorStream();  
  8.     }  
  9.     entity.setContent(inputStream);  
  10.     entity.setContentLength(connection.getContentLength());  
  11.     entity.setContentEncoding(connection.getContentEncoding());  
  12.     entity.setContentType(connection.getContentType());  
  13.     return entity;  
  14. }  

6)BasicNetwork获得返回来的Response对象,就会由Request去解析这个Response对象,因为不同的请求返回来的对象是不一样的,所以这个解析的过程必须由各个请求的实现类自己去实现,也即如ImageRequest,JsonObjectRequest对象等,都要实现自己的parseNetworkResponse方法。

HurlStack提供了三个构造函数,如下:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public HurlStack() {  
  2.     this(null);  
  3. }  
  4.   
  5. /** 
  6.  * @param urlRewriter Rewriter to use for request URLs 
  7.  */  
  8. public HurlStack(UrlRewriter urlRewriter) {  
  9.     this(urlRewriter, null);  
  10. }  
  11.   
  12. /** 
  13.  * @param urlRewriter Rewriter to use for request URLs 
  14.  * @param sslSocketFactory SSL factory to use for HTTPS connections 
  15.  */  
  16. public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) {  
  17.     mUrlRewriter = urlRewriter;  
  18.     mSslSocketFactory = sslSocketFactory;  
  19. }  

其中第一个就是Volley类中使用的构造函数,但其实最终调用的都是
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) {  
  2.         mUrlRewriter = urlRewriter;  
  3.         mSslSocketFactory = sslSocketFactory;  
  4.     }  

默认这两个类都是为null的,但是如果我们要实现对Url的拦截,对url进行一些处理的话,或者利用Https来保证数据传输的安全性的话,我们就可以传入自己实现的UrlRewriterc对象,或者添加SSlSocketFactory。不过在我们一般的项目中,也是用不到的啦,只要稍微了解一下就好了。

0 0