2017-06-28 | learn

okio

Okio 是对 Java io/nio 的一个补全

对比 Java io

Java io :

  • InputStream/OutputStream API 设计过于混乱, 不易实现
  • 用户需要关心数据存储过程
  • 可以使用 Decorator 提升性能,添加功能
  • 高层抽象存在,但是易用性不强

使用 okio 解决问题

io 操作无非读写, 需要描述读写操作

  • Source for read.
  • Sink for write.
1
2
3
4
5
6
7
8
9
10
11
12
13
public interface Sink extends Closeable, Flushable {
void write(Buffer source, long byteCount) throws IOException;
@Override void flush() throws IOException;
Timeout timeout();
@Override void close() throws IOException;
}

public interface Source extends Closeable {
long read(Buffer sink, long byteCount) throws IOException;
Timeout timeout();
@Override void close() throws IOException;
}

读写过程中又需要介质承载数据

  • Buffer
  • ByteString
1
2
3
4
5
6
public final class Buffer implements BufferedSource, BufferedSink, Cloneable{
...
}
public class ByteString implements Serializable, Comparable<ByteString> {
...
}

Buffer & ByteString

Okio 使用 BufferByteString 承载数据.

  • ByteString is an immutable sequence of bytes.
  • Buffer is a mutable sequence of bytes.

这两个类使用类了一些比较聪明的方法实现, 可以节省系统资源.
Buffer 内部使用一个 segment 的双向链表保存数据, 这样当你移动 buffer 内的数据时实际上只是重新分配 segment 而不是拷贝数据.

BufferedSink & BufferedSource

Buffer 实现了两个接口 BufferedSinkBufferedSource 以便读写数据.
查看这两个接口, 只是在 SinkSource 之上又进行一层封装, 添加了读写特点定类型等等方法.
Buffer 完整的实现了这些功能.

1
2
3
4
5
6
7
8
9
10
11
12
public interface BufferedSink extends Sink { 
..
BufferedSink writeUtf8(String string) throws IOException;
BufferedSink writeByte(int b) throws IOException;
..
}
public interface BufferedSource extends Source {
..
byte readByte() throws IOException;
short readShort() throws IOException;
..
}

层层递进的链式操作

1
2
3
4
5
6
7
8
File file = // ...
Sink fileSink = Okio.sink(file);
Sink gzipSink = new GzipSink(fileSink);
BufferedSink bufferedSink = Okio.buffer(gzipSink);

bufferedSink.writeUtf8("Hello, hello, hello!");

bufferedSink.close();

可以看到 Okio 轻松地将 Hello, hello, hello! 这段字符串经过种种变换后写入到文件中, Exciting!

Ref