Okio框架分析--之一
来源:互联网 发布:蒲城县网络党校 编辑:程序博客网 时间:2024/06/06 20:05
4.Okio
其实,上面分析的大部分类都是位于external\okhttp\okio\okio 路劲下, okio是square公司开发的开源库。
4.1 Segment
Segment是片段的意思, Segment定义如下,
final class Segment {
实际上类似于一个双向链表,部分变量如下,
static final int SIZE = 8192;// Segment维护的数组固定长度final byte[] data;//存储数据int pos;int limit;// 开始和结束点的indexboolean shared;//此Segment是否被其他Segment引用即共享数据boolean owner;//此Segment是否只被自己引用即独享数据Segment next;// 指向前置节点Segment prev;// 指向后置节点
其中一个构造方法如下,
Segment(byte[] data, int pos, int limit) { this.data = data; this.pos = pos; this.limit = limit; this.owner = false; this.shared = true;}
pop(出链表)方法如下,
public Segment pop() { Segment result = next != this ? next : null; prev.next = next; next.prev = prev; next = null; prev = null; return result; }
pop方法移除了自己,首先将自己的前后两个节点连接起来,然后将自己的前后引用置空,这样就脱离了整个双向链表,然后返回next;
push(入链表)方法如下,
public Segment push(Segment segment) { segment.prev = this; segment.next = next; next.prev = segment; next = segment; return segment;}
push方法就是在当前和next引用中间插入一个segment进来,并且返回插入的segment.
split(分割) 方法如下,
public Segment split(int byteCount) { if (byteCount <= 0 || byteCount > limit - pos) throw new IllegalArgumentException(); Segment prefix = new Segment(this); prefix.limit = prefix.pos + byteCount; pos += byteCount; prev.push(prefix); return prefix; }
split方法从Segment中分割出一个新Segment,其中新Segment包含pos~(pos+byteCount)的数据,
原Segment包含(pos+byteCount)~limit的数据,其中数据并没有真正进行移动,通过改变pos、limit索引值,
避免了copy操作。且原Segment和新Segment的shared都被置为true,标志数据不可再进行写入改动,
此方法在Buffer的write方法中调用,主要为了实现在移动数据时直接操作Segment而不是data,这样在写数据时可以达到很高的效率。
compact(压缩)方法如下,
public void compact() { if (prev == this) throw new IllegalStateException(); if (!prev.owner) return; // Cannot compact: prev isn't writable. int byteCount = limit - pos; int availableByteCount = SIZE - prev.limit + (prev.shared ? 0 : prev.pos); if (byteCount > availableByteCount) return; // Cannot compact: not enough writable space. writeTo(prev, byteCount); pop(); SegmentPool.recycle(this);}
compact方法判断前置片段的空闲容量是否能容纳此片段的数据,如果能容纳则将此片段的数据移动到前置片段,
然后回收此片段,可以防止十分短的数据占据一整个Segment而浪费空间的现象。
writeTo(写数据)方法如下,
public void writeTo(Segment sink, int byteCount) { if (!sink.owner) throw new IllegalArgumentException(); if (sink.limit + byteCount > SIZE) { // We can't fit byteCount bytes at the sink's current position. Shift sink first. if (sink.shared) throw new IllegalArgumentException(); if (sink.limit + byteCount - sink.pos > SIZE) throw new IllegalArgumentException(); System.arraycopy(sink.data, sink.pos, sink.data, 0, sink.limit - sink.pos); sink.limit -= sink.pos; sink.pos = 0; } System.arraycopy(data, pos, sink.data, sink.limit, byteCount); sink.limit += byteCount; pos += byteCount; }
writeTo方法将Segment中的数据移动到sink片段中,其中的owner和Shared用来判断如果是共享片端就无法改变片段数据,
sink.limit + byteCount > SIZE 即当要写的字节大小加上原来的字节数(尾节点索引)大于Segment的最大值时抛出异常,
但是也存在一种情况就是虽然尾节点索引和写入字节大小加起来超过,但是可能是由于前面的read方法取出数据时导致pos
索引后移(pos>0),这时就先执行移动操作,使用系统的System.arraycopy方法将从pos开始的数据移动到从0开始的位置,
然后重置pos为0,limit为移动后的尾节点索引,然后再从limit位置写入数据。
- Okio框架分析--之一
- Okio框架分析--之二
- okio分析
- OKIO源码分析
- Okio组件源码分析
- Okio使用分析
- Okio源码分析
- okio
- Sensor HAL框架分析之一
- Sensor HAL框架分析之一
- Sensor HAL框架分析之一
- InstantRun框架源码分析之一
- SPI子系统分析之一:框架
- OKIO源码分析<Segment的设计智慧>
- GEF框架分析之一(转载)
- java集合框架源码分析之一
- Python 的单元测试框架Unittest之一(TestResult类分析)
- OkIo介绍
- 说谎者悖论-C++ 会议中有一些人说谎,有一些人说真话,求最少说谎人数
- kafka概念
- python--leetcode461 hamming distance
- L练习5-1 求m到n之和(10 分)
- 简单的javaweb的思路
- Okio框架分析--之一
- Oracle分区表操作
- oracle 导入导出
- Win10和Ubuntu16.04双系统安装详解
- 细谈select函数(C语言)
- Codefources 519E. A and B and Lecture Rooms LCA
- Linux学习笔记
- vuejs视图不能及时更新的问题 ,深入响应式原理
- win10以系统管理员身份打开cmd