我正在使用 OKHTTP 进行网络连接,目前从 response.charStream() 获取 charStream,然后将其传递给 GSON 进行解析。解析和膨胀后,我再次对模型进行放气以使用流保存到磁盘。从 networkReader 到 Model 再到 DiskWriter 似乎是额外的工作。OKIO 是否可以改为从 networkReader 到 JSONParser(reader) 以及 networkReader 到 DiskWriter(reader)。基本上我希望能够从网络流中读取两次。
问问题
728 次
1 回答
1
您可以使用 a MirroredSource
(取自此 gist)。
public class MirroredSource {
private final Buffer buffer = new Buffer();
private final Source source;
private final AtomicBoolean sourceExhausted = new AtomicBoolean();
public MirroredSource(final Source source) {
this.source = source;
}
public Source original() {
return new okio.Source() {
@Override
public long read(final Buffer sink, final long byteCount) throws IOException {
final long bytesRead = source.read(sink, byteCount);
if (bytesRead > 0) {
synchronized (buffer) {
sink.copyTo(buffer, sink.size() - bytesRead, bytesRead);
// Notfiy the mirror to continue
buffer.notify();
}
} else {
sourceExhausted.set(true);
}
return bytesRead;
}
@Override
public Timeout timeout() {
return source.timeout();
}
@Override
public void close() throws IOException {
source.close();
sourceExhausted.set(true);
synchronized (buffer) {
buffer.notify();
}
}
};
}
public Source mirror() {
return new okio.Source() {
@Override
public long read(final Buffer sink, final long byteCount) throws IOException {
synchronized (buffer) {
while (!sourceExhausted.get()) {
// only need to synchronise on reads when the source is not exhausted.
if (buffer.request(byteCount)) {
return buffer.read(sink, byteCount);
} else {
try {
buffer.wait();
} catch (final InterruptedException e) {
//No op
}
}
}
}
return buffer.read(sink, byteCount);
}
@Override
public Timeout timeout() {
return new Timeout();
}
@Override
public void close() throws IOException { /* not used */ }
};
}
}
用法如下所示:
MirroredSource mirroredSource = new MirroredSource(response.body().source()); //Or however you're getting your original source
Source originalSource = mirroredSource.original();
Source secondSource = mirroredSource.mirror();
doParsing(originalSource);
writeToDisk(secondSource);
originalSource.close();
如果你想要更健壮的东西,你可以Relay
从 OkHttp 重新调整用途。
于 2016-09-28T21:04:03.503 回答