RxJava2+Retrofit2單文件下載監(jiān)聽進度封裝

RxJava2和Retrofit2用的越來越多,最近也在封裝一個通用的網(wǎng)絡請求庫,其中就包括了單文件下載的方法,所以這里進行記錄。文末附帶Demo

由于網(wǎng)上很多的方法都是使用攔截器進行進度的監(jiān)聽,個人覺得使用起來非常復雜和,所以取了個巧,在文件寫入到硬盤的時候對文件讀寫進行監(jiān)聽,就解決了retrofit2下載文件沒有進度監(jiān)聽的問題。

先上封裝之后的使用代碼,使用簡單,直接回調下載之后的文件

圖1

封裝步驟

  • 1.定義接口(使用的時候傳入完整的url,@Streaming注解可用于下載大文件)
@Streaming
    @GET
    Observable<ResponseBody> downLoadFile(@NonNull @Url String url);

  • 2.文件下載的回調方法和文件保存方法
public abstract class FileDownLoadObserver<T> extends DefaultObserver<T> {

    @Override
    public void onNext(T t) {
        onDownLoadSuccess(t);
    }
    @Override
    public void onError(Throwable e) {
        onDownLoadFail(e);
    }
    //可以重寫,具體可由子類實現(xiàn)
    @Override
    public void onComplete() {
    }
    //下載成功的回調
    public abstract void onDownLoadSuccess(T t);
    //下載失敗回調
    public abstract void onDownLoadFail(Throwable throwable);
    //下載進度監(jiān)聽
    public abstract void onProgress(int progress,long total);

    /**
     * 將文件寫入本地
     * @param responseBody 請求結果全體
     * @param destFileDir 目標文件夾
     * @param destFileName 目標文件名
     * @return 寫入完成的文件
     * @throws IOException IO異常
     */
    public File saveFile(ResponseBody responseBody, String destFileDir, String destFileName) throws IOException {
        InputStream is = null;
        byte[] buf = new byte[2048];
        int len = 0;
        FileOutputStream fos = null;
        try {
            is = responseBody.byteStream();
            final long total = responseBody.contentLength();
            long sum = 0;

            File dir = new File(destFileDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            File file = new File(dir, destFileName);
            fos = new FileOutputStream(file);
            while ((len = is.read(buf)) != -1) {
                sum += len;
                fos.write(buf, 0, len);
                final long finalSum = sum;
                //這里就是對進度的監(jiān)聽回調
                onProgress((int) (finalSum * 100 / total),total);
            }
            fos.flush();

            return file;

        } finally {
            try {
                if (is != null) is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fos != null) fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

  • 3.Retorfit構建
/**
     * 下載單文件,該方法不支持斷點下載
     *
     * @param url                  文件地址
     * @param destDir              存儲文件夾
     * @param fileName             存儲文件名
     * @param fileDownLoadObserver 監(jiān)聽回調
     */
    public void downloadFile(@NonNull String url, final String destDir, final String fileName, final FileDownLoadObserver<File> fileDownLoadObserver) {
        Retrofit retrofit = new Retrofit.Builder()
                .client(new OkHttpClient())
                .baseUrl(BASE_API.BASE_URL)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        retrofit
                .create(BASE_API.class)
                .downLoadFile(url)
                .subscribeOn(Schedulers.io())//subscribeOn和ObserOn必須在io線程,如果在主線程會出錯
                .observeOn(Schedulers.io())
                .observeOn(Schedulers.computation())//需要
                .map(new Function<ResponseBody, File>() {
                    @Override
                    public File apply(@NonNull ResponseBody responseBody) throws Exception {
                        return fileDownLoadObserver.saveFile(responseBody, destDir, fileName);
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(fileDownLoadObserver);
    }

  • 4使用,如一開始的圖
downloadFile("文件下載url","目標存儲路徑","文件名",new FileDownLoadObserver<File>() {
                            @Override
                            public void onDownLoadSuccess(File file) {
                            }
                            @Override
                            public void onDownLoadFail(Throwable throwable) {
                            }

                            @Override
                            public void onProgress(int progress,long total) {
                            }
                        });

注:github地址的內容包括了文件上傳進度封裝的方法,具體查看RRMLib文件夾下的方法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容