我有一个PDF阅读器应用程序,需要下载大型PDF文件(例如136MB),我正在使用retrofit2-beta2进行此过程。问题是我总是会因内存不足而出错。如何告诉retrofit我将要下载大文件,请直接将字节流给我?
我的接口是:
@GET("url")
Call<ResponseBody> getData(params);
我有一个ProgressResponseBody类,它扩展了ResponseBody,并在此处设置了一个progressListener,以便能够刷新进度条。
在onResponse函数中,我只需获取InputStream。
InputStream input = response.body().byteStream();
FileOutputStream out = new FileOutputStream(file);
int bufferSize=1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while (len = input.read(buffer) != -1) {
out.write(buffer,0,len);
}
if(out!=null)
out.close();
更新
我已经在接口中添加了@Stream,但现在在ProgressResponseBody.java文件中遇到了NetworkOnMainThreadException异常。错误是在超级.read(sink,byteCount); 行中抛出的。如何将其放入单独的线程中?
@Override
public BufferedSource source() throws IOException {
if (bufferedSource == null) {
bufferedSource = Okio.buffer(source(responseBody.source()));
}
return bufferedSource;
}
private Source source(Source source) {
return new ForwardingSource(source) {
long totalBytesRead = 0L;
@Override
public long read(Buffer sink, long byteCount) throws IOException {
long bytesRead = super.read(sink, byteCount);
totalBytesRead += bytesRead != -1 ? bytesRead : 0;
progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
return bytesRead;
}
};
}
@Streaming
时,response.body()
是网络调用,所以你现在需要将其移出主线程的责任。对于普通调用,Retrofit会为您完成此操作。将响应体的处理移动到新线程(通过AsyncTask或类似方式)。 - iagreen