Volley的框架解读三(字节流的优化)
来源:互联网 发布:电视tv软件 编辑:程序博客网 时间:2024/06/04 00:54
先看UML。其实用到这两个东西就是在访问网络的时候
源码解读绝招二:你还记得UML,和设计模式二人组么,用程序员共用的语言去看他们吧~
在对响应的实体进行操作的时候,使用到了byte[] ,由于volley是轻量级频次高的网络请求框架,因此会大量使用到byte[] ,这样的话会频繁创建和销毁byte[]。为了提高性能,volley定义了一个byte[]缓冲池,即ByteArrayPool 。
在ByteArrayPool 内,定义了 两个集合,分别是存储按大小顺序排列byte[]的list 和 按使用先后顺序排列byte[]的LinkedList。在volley中所需要使用到的byte[]从该缓冲池中来取,当byte[]使用完毕后再归还到该缓冲池,从而避免频繁的创建和销毁byte[]。
如下:
/** * 按使用的先后时间顺序排序 */ private List<byte[]> mBuffersByLastUse = new LinkedList<byte[]>(); /** * 按大小顺序排序 */ private List<byte[]> mBuffersBySize = new ArrayList<byte[]>(64); /** * 池中所有byte[]的长度之和 */ private int mCurrentSize = 0; /** * 池中单个byte[]的最大长度 */ private final int mSizeLimit;
以下内容可能跟数据结构相关了,比如数据结构,取,存,删除,容量自动扩增等等
数据取出
简而言之就是如果从缓存池中找不到长度比他大的,就新建一个,有的话就直接返回Byte[]
public synchronized byte[] getBuf(int len) { //遍历按长度排序的池 for (int i = 0; i < mBuffersBySize.size(); i++) { byte[] buf = mBuffersBySize.get(i); //如果当前的byte[]的长度大于给定的长度,就返回该byte[] if (buf.length >= len) { //池中所有byte[]的长度之和减去返回出去的byte[]的长度 mCurrentSize -= buf.length; //从按顺序排列的池中移除该byte[] mBuffersBySize.remove(i); //从按使用顺序排列的池中移除该byte[],表示该byte[]正在使用中,其他不能再使用该byte[] mBuffersByLastUse.remove(buf); return buf; } } //创建一个新的byte[] return new byte[len]; }
数据存入
这里就是用完又要把byte[]放回来了。
数据结构一般不能忘记边界考虑了,比如为空,或者超过限制byte[]最大长度就不存入了,同时也要存入缓存池
public synchronized void returnBuf(byte[] buf) { //如果为空或者超过了设定的单个byte[]的最大长度 那么就不再池中保存该byte[] if (buf == null || buf.length > mSizeLimit) { return; } //在按使用时间顺序排序的池中添加该byte[] mBuffersByLastUse.add(buf); //利用二分查找法,找出在按大小排序的池中该byte[]应该存放的位置 int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR); //如果找不到,则返回-1 if (pos < 0) { //当找不到时,也就是在0位置添加 pos = -pos - 1; } mBuffersBySize.add(pos, buf); //增加最大长度 mCurrentSize += buf.length; //清理,不能超过字节总数最大值 trim(); }
数据删除
上面有有个trim,也即是删除数据方法
private synchronized void trim() { //当现有字节总数超过了设定的界限,那么需要清理 while (mCurrentSize > mSizeLimit) { //按照使用的先后顺序来倾全力,最新使用的最先被清除 byte[] buf = mBuffersByLastUse.remove(0); //同样在该池中也清除 mBuffersBySize.remove(buf); //减小现有字节最大长度 mCurrentSize -= buf.length; } }
写到这里的时候,还差一个自动扩增方法怎么没有呢,Volley是把它和ByteArrayOutputStream联合在一起了。
你没猜错又是组合,ByteArrayOutputStream的写入方法中,有自动扩存
/** * 从buffer的offset位置读len长度的内容,写入到输出流的byte[](buf)中 */ @Override public synchronized void write(byte[] buffer, int offset, int len) { expand(len); super.write(buffer, offset, len); }
expand方法~
/** * Ensures there is enough space in the buffer for the given number of additional bytes. * 扩充当前输出流正在使用的byte[]的大小 */ private void expand(int i) { /* Can the buffer handle @i more bytes, if not expand it */ if (count + i <= buf.length) { //当已经写入的字节数加上预计扩展的字节数之和,仍然不大于当前的byte[]的长度时,不需要扩展 return; } //当当前的byte[]不再满足时,需要从byte[]缓冲池中获取一个byte[],大小为(count + i) * 2 byte[] newbuf = mPool.getBuf((count + i) * 2); //将当前的byte[]内容复制到新的byte[]中 System.arraycopy(buf, 0, newbuf, 0, count); //将旧的byte[]进行回收到byte[]缓冲池中 mPool.returnBuf(buf); buf = newbuf; }
当然也把存取也封装进了ByteArrayOutputStream
public PoolingByteArrayOutputStream(ByteArrayPool pool, int size) { mPool = pool; /** * buf,该输出流将要内容写入的目标byte[],如果多次写入,buf长度不够的时候需要扩展长度 */ buf = mPool.getBuf(Math.max(size, DEFAULT_SIZE)); } @Override public void close() throws IOException { //当输出流关闭的时候,释放该byte[]回到byte缓冲池中 mPool.returnBuf(buf); buf = null; super.close(); } @Override public void finalize() { //当垃圾回收机制准备回收该输出流时,将该byte[]回收到缓冲池 mPool.returnBuf(buf); }
构造方法中,取出,close的时候返回,简直完美,有不有
这些缓存池用在那个地方呢? 也就是上一节用来缓存响应数据的
private byte[] entityToBytes(HttpEntity entity) throws IOException, ServerError { PoolingByteArrayOutputStream bytes = new PoolingByteArrayOutputStream(mPool, (int) entity.getContentLength()); byte[] buffer = null; try { InputStream in = entity.getContent(); if (in == null) { throw new ServerError(); } buffer = mPool.getBuf(1024); int count; while ((count = in.read(buffer)) != -1) { bytes.write(buffer, 0, count);//从buffer中读取内容写入输出流中的byte[]中 } return bytes.toByteArray(); } finally { try { // Close the InputStream and release the resources by "consuming the content". entity.consumeContent(); } catch (IOException e) { // This can happen if there was an exception above that left the entity in // an invalid state. VolleyLog.v("Error occured when calling consumingContent"); } mPool.returnBuf(buffer); bytes.close(); } }
- Volley的框架解读三(字节流的优化)
- Volley框架的基本解读(三)
- volley框架的解读
- Volley框架解读(三)
- Volley的框架解读七(Request)
- Volley的框架解读一(Http的封装)
- Android Volley框架的使用(三)
- Android Volley框架的使用(三)
- Volley的框架解读二(Http访问及处理)
- Volley的框架解读四(请求队列RequestQueue)
- Volley的框架解读五(网络调度NetworkDispatcher)
- Volley框架的基本解读(一)
- Volley框架的基本解读(二)
- Volley框架的基本解读(四)
- Volley框架的基本解读(五)
- Volley框架的基本解读(六)
- Volley框架的基本解读(七)
- Volley框架的基本解读(八)
- Kaggle入门系列:(二)机器学习环境搭建
- JVM相关小结
- fengzhuang
- java实现定时任务的三种方法
- 解决Use 'LimitInternalRecursion' to increase the limit if necessary的问题 CodeIgniter .htaccess
- Volley的框架解读三(字节流的优化)
- WEB跨域资源共享:Cross-origin Resource Sharing(CORS)
- 数据挖掘之决策树归纳算法的Python实现
- ife task3
- 53. Maximum Subarray(最大子序列)
- 1004 线性表操作
- 简述策略模式
- Ansible部署rsync
- KindEditor不兼容Firefox出现添加图片按钮不显示