OkHttp3网络请求(三)之下载篇

本文介绍了一个基于OkHttp实现的下载库OkDownload,该库通过自定义拦截器和响应体来实现文件的下载功能。文章详细解释了OkDownload的类结构,包括OkDownload类、DownloadInterceptor拦截器、DownloadCallback回调接口和DownloadResponse响应体的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、OkClient.java

public class OkDownload {

    private static OkDownload instance;

    private Handler mHandler;
    private OkHttpClient okHttpClient;
    private DownloadInterceptor interceptor = new DownloadInterceptor();

    private OkDownload() {
        if (okHttpClient == null) {
            okHttpClient = new OkHttpClient.Builder()
                    .addInterceptor(interceptor)
                    .build();
        }
        if (mHandler == null) mHandler = new Handler(Looper.getMainLooper());
    }

    public static OkDownload getInstance() {
        if (instance == null) {
            synchronized (OkDownload.class) {
                if (instance == null) {
                    instance = new OkDownload();
                }
            }
        }
        return instance;
    }

    public void download(String url, String filePath, DownloadCallback callback) {
        download(url, filePath, getFileName(url), callback);
    }

    public void download(String url, String filePath, String fileName, DownloadCallback callback) {
        interceptor.setCallback(mHandler, callback);
        Request request = new Request.Builder()
                .url(url)
                .build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                if (callback != null) callback.onFailed(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream is = null;
                byte[] b = new byte[2048];
                int len;
                FileOutputStream fos = null;
                if (callback != null) mHandler.post(callback::onStart);
                try {
                    is = response.body().byteStream();
                    File file = new File(filePath, fileName);
                    fos = new FileOutputStream(file);
                    while ((len = is.read(b)) != -1) {
                        fos.write(b, 0, len);
                    }
                    fos.flush();
                    // 如果下载文件成功,第一个参数为文件的绝对路径
                    if (callback != null) mHandler.post(()-> callback.onComplete(file.getAbsolutePath()));
                } catch (Exception e) {
                    if (callback != null) callback.onFailed(e);
                } finally {
                    if (is != null) {
                        is.close();
                    }
                    if (fos != null) {
                        fos.close();
                    }
                }
            }
        });
    }

    private String getFileName(String path) {
        int separatorIndex = path.lastIndexOf("/");
        return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1);
    }
}

2、拦截器
DownloadInterceptor.java

public class DownloadInterceptor implements Interceptor {

    private DownloadCallback callback;
    private Handler mHandler;

    public void setCallback(Handler mHandler, DownloadCallback callback) {
        this.callback = callback;
        this.mHandler = mHandler;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        return response.newBuilder()
                .body(new DownloadResponse(mHandler, response, callback))
                .build();
    }
}

3、回调接口
DownloadCallback.java

public interface DownloadCallback {

    void onStart();

    // unit : kb
    void update(long readed, long length);

    void onComplete(String absolutePath);

    void onFailed(Exception e);
}

4、响应体
DownloadResponse.java

public class DownloadResponse extends ResponseBody {

    private Response response;
    private Handler mHandler;
    private DownloadCallback callback;

    public DownloadResponse(Handler mHandler, Response response, DownloadCallback callback) {
        this.response = response;
        this.callback = callback;
        this.mHandler = mHandler;
    }

    @Override
    public MediaType contentType() {
        return response.body().contentType();
    }

    @Override
    public long contentLength() {
        return response.body().contentLength();
    }

    @Override
    public BufferedSource source() {
        return Okio.buffer(new ForwardingSource(response.body().source()) {

            private long byteReaded = 0;

            @Override
            public long read(Buffer sink, long byteCount) throws IOException {
                long read = super.read(sink, byteCount);
                byteReaded += read == -1 ? 0 : read;
                if (callback != null) {
                    mHandler.post(() -> callback.update(byteReaded / 1024, response.body().contentLength() / 1024));
                }
                return byteReaded;
            }
        });
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值