RxJava+Retrofit+OkHttp深入浅出-终极封装四(多文件下载之断点续传)
背景
断点续传下载一直是移动开发中必不可少的一项重要的技术,同样的Rxjava和Retrofit的结合让这个技术解决起来更加的灵活,我们完全可以封装一个适合自的下载框架,简单而且安全!
效果
实现
下载和之前的http请求可以相互独立,所以我们单独给download建立一个工程moudel处理
1.创建service接口
和以前一样,先写接口
注意:Streaming是判断是否写入内存的标示,如果小文件可以考虑不写,一般情况必须写;下载地址需要通过@url动态指定(不适固定的),@head标签是指定下载的起始位置(断点续传的位置)
/*断点续传下载接口*/
@Streaming/*大文件需要加入这个判断,防止下载过程中写入到内存中*/
@GET
Observable<ResponseBody> download(@Header("RANGE") String start, @Url String url);
2.复写ResponseBody
和之前的上传封装一样,下载更加的需要进度,所以我们同样覆盖ResponseBody类,写入进度监听回调
/**
* 自定义进度的body
* @author wzg
*/
public class DownloadResponseBody extends ResponseBody {
private ResponseBody responseBody;
private DownloadProgressListener progressListener;
private BufferedSource bufferedSource;
public DownloadResponseBody(ResponseBody responseBody, DownloadProgressListener progressListener) {
this.responseBody = responseBody;
this.progressListener = progressListener;
}
@Override
public BufferedSource source() {
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);
// read() returns the number of bytes read, or -1 if this source is exhausted.
totalBytesRead += bytesRead != -1 ? bytesRead : 0;
if (null != progressListener) {
progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
}
return bytesRead;
}
};
}
}
3.自定义进度回调接口
/**
* 成功回调处理
* Created by WZG on 2016/10/20.
*/
public interface DownloadProgressListener {
/**
* 下载进度
* @param read
* @param count
* @param done
*/
void update(long read, long count, boolean done);
}
4.复写Interceptor
复写Interceptor,可以将我们的监听回调通过okhttp的client方法addInterceptor自动加载我们的监听回调和ResponseBody
/**
* 成功回调处理
* Created by WZG on 2016/10/20.
*/
public class DownloadInterceptor implements Interceptor {
private DownloadProgressListener listener;
public DownloadInterceptor(DownloadProgressListener listener) {
this.listener =