Volley源码学习(二):网络请求处理,HurlStack类,BasicNetwork类,ByteArrayPool,PoolingByteArrayOutputStream
来源:互联网 发布:unity3d 离散事件仿真 编辑:程序博客网 时间:2023/11/29 04:35
一.源码解析
volley用于处理网络请求的HurlStack类和BasicNetwork类,继承HttpStack接口
1.接口HttpStack,定义了方法HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders),处理网络请求,获得HttpResponse。
2.类HurlStack:使用httpconnection处理网络请求
主要方法:
方法:performRequest(Request<?> request, Map<String, String> additionalHeaders)
逻辑流程:获得url,new map添加request里的headers和additionalHeaders→有mUrlRewriter就重写url→获得connection = openConnection(parsedUrl, request);→遍历map,connection.addRequestProperty,为connection添加headers.→获得responseCode并new responseStatus→response = new BasicHttpResponse(responseStatus);→response.setEntity,设置entity→遍历,将connection的headers添加到response里,最后返回。
方法:setConnectionParametersForRequest(HttpURLConnection connection,Request<?> request)
根据request,为connection设置method,post,get,delete,put等
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; }
3.类BaseNetwork
主要方法
方法:addCacheHeaders(Map<String, String> headers, Cache.Entry entry),如果存在Cache.Entry,headers.put("If-Modified-Since", DateUtils.formatDate(refTime));
方法:NetworkResponse performRequest(Request<?> request):包装HurlStack类的方法,增加一些其他操作。
调用addCacheHeaders方法,为request增加CacheHeaders→调用hurlStack的performRequest方法获得httpResponse→获得statusLine,获得statusCode
→如果StatusCode==304,则直接返回NetworkResponse,将NetWorkResponse的notModified设为true→对于204等没有content的状态码,再确认一次,将
httpResponse的entity转换到responseContents里→状态码为200-299时,返回NetworkResponse,但notModified为false.→不是时,抛出IOException
→在catch里根据responseContent是否为null,进行对应处理,抛出异常。
方法:entityToBytes(HttpEntity entity),将entity转换为byte[],利用到PoolingByteArrayOutputStream类,ByteArrayPool类,之前ByteArrayPool类是一个持有
不同长度的byte[]的pool,可以提供大于目标size的byte[],防止不同size的byte[]重复创建,提供性能。PoolingByteArrayOutputStream则是利用ByteArrayPool
提供的byte[]的输出流。
public NetworkResponse performRequest(Request<?> request) throws VolleyError { long requestStart = SystemClock.elapsedRealtime(); while (true) { HttpResponse httpResponse = null; 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); StatusLine statusLine = httpResponse.getStatusLine(); 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); } // Some responses such as 204s do not have content. We must check. if (httpResponse.getEntity() != null) { 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); } 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) { int statusCode = 0; NetworkResponse networkResponse = null; if (httpResponse != null) { statusCode = httpResponse.getStatusLine().getStatusCode(); } else { 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); } } else { throw new NetworkError(networkResponse); } } } }
3.类NetworkResponse
NetworkResponse(int statusCode, byte[] data, Map<String, String> headers,boolean notModified)构造方法就可以看出用途
包装后,如果server返回304,notModified就是true说明在指定时间未修改,直接从本地cache获取。
4.类ByteArrayPool,提供不同size的byte[],提高性能
getBuf(int len),trim(),returnBuf(byte[] buf)3个主要方法。
public class ByteArrayPool
mBuffersByLastUse = new LinkedList<byte[]>(); //用于将最近使用的byte[]添加到末尾,删除byte[]时,删除头部的,即删除最久不用的
private List<byte[]> mBuffersBySize = new ArrayList<byte[]>(64); //按大小顺序排列的list<pre name="code" class="html">public synchronized void returnBuf(byte[] buf) { //将buf添加到pool里
if (buf == null || buf.length > mSizeLimit) { return; } mBuffersByLastUse.add(buf); //添加到末尾,表明最近使用的 int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR); //使用二分法将buf插入到mBufferBysize里 if (pos < 0) { pos = -pos - 1; } mBuffersBySize.add(pos, buf); mCurrentSize += buf.length; trim(); //添加后,确认是否超出limitSize,超出就删除旧的byte[] }<pre name="code" class="html"> private synchronized void trim() { while (mCurrentSize > mSizeLimit) { byte[] buf = mBuffersByLastUse.remove(0); //找到eldest的byte[] mBuffersBySize.remove(buf); //删除 mCurrentSize -= buf.length; } }
public synchronized byte[] getBuf(int len) { //根据len获得大于该len的byte[] for (int i = 0; i < mBuffersBySize.size(); i++) { byte[] buf = mBuffersBySize.get(i); if (buf.length >= len) { mCurrentSize -= buf.length; mBuffersBySize.remove(i); //移除buf mBuffersByLastUse.remove(buf); return buf; } } return new byte[len]; }
5.类PoolingByteArrayOutputStream,使用ByteArrayPool的ByteArrayOutputStream,提供性能
private void expand(int i) { //扩展读取时用的buf /* Can the buffer handle @i more bytes, if not expand it */ if (count + i <= buf.length) { return; } byte[] newbuf = mPool.getBuf((count + i) * 2); //从mPool里获得byte[],size至少是原来的2倍 System.arraycopy(buf, 0, newbuf, 0, count); mPool.returnBuf(buf); //将不用的buf return到pool里保存 buf = newbuf; //buf指向newbuf }</span><pre name="code" class="html"> public synchronized void write(byte[] buffer, int offset, int len) { expand(len); //写时调用expand方法,检查是否需要扩展, super.write(buffer, offset, len); }
@Override public void close() throws IOException { //关闭,或回收时都将buf 还回pool mPool.returnBuf(buf); buf = null; super.close(); } @Override public void finalize() { mPool.returnBuf(buf); }
0 0
- Volley源码学习(二):网络请求处理,HurlStack类,BasicNetwork类,ByteArrayPool,PoolingByteArrayOutputStream
- Volley源码学习笔记_RequestQueue和BasicNetWork
- volley PoolingByteArrayOutputStream
- Volley ByteArrayPool
- Android学习之网络请求(volley)二
- Android中的volley_4_执行网络请求的接口Network及其实现类BasicNetwork
- 聊聊Volley源码(网络请求过程)
- Google网络请求框架Volley源码浅析(二)
- Volley网络请求源码分析
- Volley -- 网络请求源码分析
- 4、Volley解析(二),源码的深入分析一,缓存线程和网络请求线程
- Volley中的PoolingByteArrayOutputStream
- volley源码解析(六)--HurlStack与HttpClientStack之争
- Volley源码学习(一):Volley类,RequestQueue类
- Volley请求网络简单学习
- Volley学习笔记(二):使用Volley加载网络图片
- Volley源码解析(一):网络请求内容
- Volley封装的网络请求类
- 哈理工oj 2035 Diablo【BFS+DFS】
- 一个字符串中,找到出现次数最多的字符
- 样式布局分享-基于frozen.js的移动OA
- c++引用和指针,不为人知的秘密。
- 「每周review」关于Emacs的学习XMind
- Volley源码学习(二):网络请求处理,HurlStack类,BasicNetwork类,ByteArrayPool,PoolingByteArrayOutputStream
- HTTP multipart/form-data格式之文件上传
- 快速排序
- 关于Opencv图像的转换(YUV420sp)
- LINQ
- Java设计模式之单例(Singleton)模式
- poj 3420 Quad Tiling 状压dp+矩阵快速幂
- HDU4046 Panda(线段树)
- Linux下常用指令