Volley的框架解读一(Http的封装)
来源:互联网 发布:黑客查看网站php源码 编辑:程序博客网 时间:2024/06/05 16:26
先瞄瞄UML类图
在Volley中真正的网络请求是由HttpStack定义的,这是一个接口,它唯一的一个方法就是执行网路请求获取响应。而HttpClientStack和HurlStack是该接口的实现类,对应不同的网络请求的底层实现,HttpClientStack是基于HttpClient的,HurlStack是基于HttpURLConnection的。
先看看这个父接口(HttpStack)
源码解读绝招一:看父类,接口,这样你才知道这个类是干啥的,应该有什么行为
/** * Volley中真正去执行联网的类,返回的信息封装成HttpResponse */public interface HttpStack { /** * 真正去执行联网的方法 */ public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError;}
Volley本来是支持HttpURLConnection,还有HttpClient的,当然处于现在这个年代,HttpClient被废弃了,所以只看HttpURLConnection的封装
另外说一点Volley中的Request,从字面理解上是请求,但是其实不是一个真正的网络请求,个人理解为是对真正的网络请求的各个属性的描述。
HttpStack是真正的网络请求,Request则是封装了超时时间、请求方式、参数、url等网络请求所必须的参数。通过变换不同的属性参数(最基本的如请求方式GET POST),可以获取不同的网络请求。
OK,现在在说下我对于HttpClientStack和HurlStack的理解,二者的工作思路是这样的:
1. 首先从Volley的Request内获取各个属性、如超时间、请求方式、参数和url2.创建网络请求,HttpClientStack是创建HttpClient ,HurlStack是创建HttpURLConnection3.对网络请求设置各个属性参数4.定义执行网路请求的方法,并获取响应,将响应返回出去
上面说的是思路,现在看一下源码细节是怎么写的,一些得从performRequest开始
源码细节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); //1.得到一个HttpURLConnection HttpURLConnection connection = openConnection(parsedUrl, request); //2.设置响应头 for (String headerName : map.keySet()) { connection.addRequestProperty(headerName, map.get(headerName)); } //3.设置请求方式 setConnectionParametersForRequest(connection, request); //4.响应的协议版本 ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1); //5.获取状态码 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."); } //6.根据链接获取响应的状态码响应信息 StatusLine responseStatus = new BasicStatusLine(protocolVersion, connection.getResponseCode(), connection.getResponseMessage()); //创建响应 BasicHttpResponse response = new BasicHttpResponse(responseStatus); //给响应设置响应体,响应体来自于链接 response.setEntity(entityFromConnection(connection)); //将得到的头信息赋值给实体类(BasicHttpResponse) 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; }
看传入参数Request,里面有设置了很多http的属性,如超时,是否缓存,还有一个参数设置头信息
再看看其中几个重要方法
- openConnection
- setConnectionParametersForRequest 设置请求方式
- entityFromConnection
openConnection封装细节
/** * 设置HttpURLConnection 一些参数以及支持https * @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) { ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory); } return connection; }
没啥好说的就是创建了HttpURLConnection,设置一些属性
entityFromConnection封装细节
/** * 将connection得到的信息封装成实体(BasicHttpEntity)返回 * @param connection * @return */ 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; }
这里就是从HttpURLConnection获取接口信息,封装成HttpEntity,返回给调用者BasicNetWork
Volley的真正的网络请求就是这些了,注意这里是定义网络请求和网络请求的方法,但是调用执行网络请求其实是在NetWork接口及其实现类BasicNetwork内。
如果对于HttpURLConnection 不太了解,或者忘记的差不对了可以看看我前面文章
Volley的框架解读准备一HttpURLConnection
- Volley的框架解读一(Http的封装)
- Volley的框架解读二(Http访问及处理)
- Volley框架的基本解读(一)
- Volley的框架解读准备一HttpURLConnection
- volley框架的解读
- Volley的框架解读七(Request)
- Volley框架的二次封装
- Volley框架的二次封装
- Volley的框架解读三(字节流的优化)
- Volley--http框架的实例
- Volley的框架解读四(请求队列RequestQueue)
- Volley的框架解读五(网络调度NetworkDispatcher)
- Volley框架的基本解读(二)
- Volley框架的基本解读(三)
- Volley框架的基本解读(四)
- Volley框架的基本解读(五)
- Volley框架的基本解读(六)
- Volley框架的基本解读(七)
- LeetCode-42-Trapping Rain Water 贪心或单调栈
- 如何使用logstash更新已有的elasticsearch记录
- 自配Tomcat的启动
- SVN库迁移
- 我遇到的前端面试题2017
- Volley的框架解读一(Http的封装)
- 相反数
- C语言小程序2--致新手
- Java基础部分全套教程
- C++随机数求圆周率
- 快速制作演示动画的工具TurboDemo常见问题合集(三)
- bootstrap响应式兼容PC和移动端图片无缝滚动效果demo
- Live555学习之(五)------live555ProxyServer.cpp的学习
- Git的本地工作环境干净的的脚本