Volley框架的基本解读(四)
2016-05-24 16:26
471 查看
废话不多说,放上Volley框架的基本解读(三)的链接,我们继续往下看,先来看看网络执行类HttpStack的源码:
这是一个接口,里面有一个与Network接口同名,但又不一样的方法。
具体实现是由Volley.newRequestQueue中根据api版本不同,创建的HurlStack或HttpClientStack,前面已经说过两者之间的差别,我们选版本高的来讲,这里值得一提的是,之所以在api9之后不用HttpClient,是因为它有所缺陷,好了,进入正题:
继续看:
再看:
UrlRewriter是HurlStack中的一个内部接口,用于URL的重置,我们给的是null,所以不用管它,SSLSocketFactory是https协议用到的类,我们给的也是null,所以也不需要管它,直入主题看performRequest方法:
前面都很简单,我们直接看第16行的openConnection方法:
再看createConnection方法:
很简单吧,仅仅只是封装了(HttpURLConnection) url.openConnection()这一句代码而已,那么上面也就简单了,只是对网络请求进行了一些简单的设置,判断是否是https协议,进行设置。
这里提一点request.getTimeoutMs()获取到的时间其实是DefaultRetryPolicy中mCurrentTimeoutMs,当请求重试时,连接超时的时间会被延长。
随后就是添加请求头,setConnectionParametersForRequest方法用于确定请求方式:
包含GET,DELETE,POST,PUT等等,第一种请无视它,大概的意思是这是过时的,需要处理的向后兼容性,如果该请求的正文无效,则该假设是该请求是GET,否则是POST,老实说我也不知道它想表达什么意思,如果有大神知道还望指教!
之后就是为了统一返回方式,将HttpURLConnection中的属性给予了封装,先是http协议版本,然后封装成状态行,再然后放入BasicHttpResponse中,设置实体,entityFromConnection方法,猜也猜的到是做什么用的:
很简单,我就不废话了。
最后添加响应头,一个HttpResponse就封装完成了。
到此Volley网络请求这一条线,我们已经全部走完了,希望各位读者能有所收获!
/** * An HTTP stack abstraction. */ public interface HttpStack { /** * Performs an HTTP request with the given parameters. * * <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; }
这是一个接口,里面有一个与Network接口同名,但又不一样的方法。
具体实现是由Volley.newRequestQueue中根据api版本不同,创建的HurlStack或HttpClientStack,前面已经说过两者之间的差别,我们选版本高的来讲,这里值得一提的是,之所以在api9之后不用HttpClient,是因为它有所缺陷,好了,进入正题:
public HurlStack() { this(null); }
继续看:
public HurlStack(UrlRewriter urlRewriter) { this(urlRewriter, null); }
再看:
public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) { mUrlRewriter = urlRewriter; mSslSocketFactory = sslSocketFactory; }
UrlRewriter是HurlStack中的一个内部接口,用于URL的重置,我们给的是null,所以不用管它,SSLSocketFactory是https协议用到的类,我们给的也是null,所以也不需要管它,直入主题看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); 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); 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; }
前面都很简单,我们直接看第16行的openConnection方法:
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 // 如果是https协议 if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) { ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory); } return connection; }
再看createConnection方法:
protected HttpURLConnection createConnection(URL url) throws IOException { return (HttpURLConnection) url.openConnection(); }
很简单吧,仅仅只是封装了(HttpURLConnection) url.openConnection()这一句代码而已,那么上面也就简单了,只是对网络请求进行了一些简单的设置,判断是否是https协议,进行设置。
这里提一点request.getTimeoutMs()获取到的时间其实是DefaultRetryPolicy中mCurrentTimeoutMs,当请求重试时,连接超时的时间会被延长。
随后就是添加请求头,setConnectionParametersForRequest方法用于确定请求方式:
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; default: throw new IllegalStateException("Unknown method type."); } }
包含GET,DELETE,POST,PUT等等,第一种请无视它,大概的意思是这是过时的,需要处理的向后兼容性,如果该请求的正文无效,则该假设是该请求是GET,否则是POST,老实说我也不知道它想表达什么意思,如果有大神知道还望指教!
之后就是为了统一返回方式,将HttpURLConnection中的属性给予了封装,先是http协议版本,然后封装成状态行,再然后放入BasicHttpResponse中,设置实体,entityFromConnection方法,猜也猜的到是做什么用的:
/** * Initializes an {@link HttpEntity} from the given {@link HttpURLConnection}. * @param connection * @return an HttpEntity populated with data from <code>connection</code>. * * 将HttpURLConnection换成HttpEntity */ 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; }
很简单,我就不废话了。
最后添加响应头,一个HttpResponse就封装完成了。
到此Volley网络请求这一条线,我们已经全部走完了,希望各位读者能有所收获!
相关文章推荐
- 使用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的关闭事件