OkHttp3網絡請求(三)之下載篇

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;
            }
        });
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章