服务器端如何实现下载(Tomcat)可以看我之前写的博客
Tomcat下文件下载与上传的简单实现,这篇博客主要是写安卓端如何监听下载进度,并转到相应的UI界面进行处理。
主要分三步:
- 创建一个Listener接口用于监听下载进度
- 创建一个内置了监听器的ResponseBody的子类用于实时获取进度
- 为OKHttpClient添加拦截器处理原本的Response
第一步:创建一个Listener接口用于监听下载进度
public interface ProgressListener {
/**
* @param progress 已经下载或上传字节数
* @param total 总字节数
* @param done 是否完成
*/
void onProgress(long progress, long total, boolean done);
}
第二步:实现继承ResponseBody的子类
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;
public class ProgressResponseBody extends ResponseBody {
private final ResponseBody responseBody;
private final ProgressListener progressListener;
private BufferedSource bufferedSource;
public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
this.responseBody = responseBody;
this.progressListener = progressListener;
}
@Override
public MediaType contentType() {
return responseBody.contentType();
}
@Override
public long contentLength() {
return responseBody.contentLength();
}
@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);
totalBytesRead += bytesRead != -1 ? bytesRead : 0;
progressListener.onProgress(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
return bytesRead;
}
};
}
}
第三步:为OKHttpClient添加拦截器
OkHttpClient build = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response proceed = chain.proceed(chain.request());
return proceed.newBuilder().body(new ProgressResponseBody(
proceed.body(),
new ProgressListener() {
@Override
public void onProgress(long progress, long total, boolean done) {
Log.i(TAG, "onProgress: " + progress + "-" + total + "-" + done);
}
}
)).build();
}
}).build();
剩下的步骤就是正常的Retrofit请求的步骤了:
Retrofit retrofit = new Retrofit.Builder()
.client(build)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(Request.host)
.build();
Request request = retrofit.create(Request.class);
...
之后正常使用,可以发现控制台已经有了相应的输出,这说明监听进度已经实现,接下来就是如何将监听器里原本的输出换成相应的UI更新了,这里不做赘述。