最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Ok+Rxjava+retrofit實(shí)現(xiàn)斷點(diǎn)續(xù)傳下載

 更新時(shí)間:2019年06月22日 16:27:28   作者:Super_Ks  
這篇文章主要為大家詳細(xì)介紹了基于Ok+Rxjava+retrofit實(shí)現(xiàn)斷點(diǎn)續(xù)傳下載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文為大家分享了實(shí)現(xiàn)斷點(diǎn)續(xù)傳下載的具體代碼,供大家參考,具體內(nèi)容如下

1、基于Ok+Rxjava實(shí)現(xiàn)斷點(diǎn)續(xù)傳下載

2、基于Ok+Rxjava+Retrofit實(shí)現(xiàn)斷點(diǎn)續(xù)傳下載

上一篇博客中介紹了基于Ok+Rxjava實(shí)現(xiàn)斷點(diǎn)續(xù)傳下載,這一篇給大家介紹下基于Ok+Rxjava+Retrofit實(shí)現(xiàn)斷點(diǎn)續(xù)傳下載,demo下載地址,效果圖跟上一篇圖片一樣,哈哈

 說下我的大致思路吧(跟上一篇略有不同):根據(jù)文件下載url按照自己定義的規(guī)則生成文件名,判斷本地同路徑下是否存在此文件,如果存在,文件大小與服務(wù)器上獲取的文件大小一致的情況下,則覆蓋本地文件重新下載;如果文件比服務(wù)器獲取的文件大小小,則執(zhí)行斷點(diǎn)下載,從本地文件長度處開始下載。如果文件不存在,則從0字節(jié)開始下載。

還有的不同是,這里需要重新ResponseBody的source()方法,在這里監(jiān)聽文件下載的進(jìn)度,然后通過我么自定義的Downloadinterceptor把我們重新的DownloadResponseBody給設(shè)置進(jìn)去,從而完成我們的進(jìn)度監(jiān)聽工作。

下面還是上主要代碼:

首先重寫ResponseBody

public class DownloadResponseBody extends ResponseBody {
 private ResponseBody responseBody;
 
 //進(jìn)度回調(diào)接口
 private DownFileCallback downFileCallback;
 
 private BufferedSource bufferedSource;
 private String downUrl;
 
 
 public DownloadResponseBody(ResponseBody responseBody, DownFileCallback downFileCallback, String downUrl) {
 this.responseBody = responseBody;
 this.downFileCallback = downFileCallback;
 this.downUrl = downUrl;
 }
 
 @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;
 File file = new File(DownloadManager.getInstance().getTemporaryName(downUrl));
 
 @Override
 public long read(Buffer sink, long byteCount) throws IOException {
 long bytesRead = super.read(sink, byteCount);
 totalBytesRead += bytesRead != -1 ? bytesRead : 0;
 if (null != downFileCallback) {
 if (bytesRead != -1) {
 long loacalSize = file.length();//本地已下載的長度
 long trueTotal = loacalSize + responseBody.contentLength() - totalBytesRead;//文件真實(shí)長度
 downFileCallback.onProgress(trueTotal,loacalSize);
 } else {
 
 }
 
 }
 return bytesRead;
 }
 };
 
 }
}

重寫Interceptor

public class Downloadinterceptor implements Interceptor {
 
 private DownFileCallback downFileCallback;
 
 private String downUrl;
 
 public Downloadinterceptor(DownFileCallback listener,String downUrl) {
 this.downFileCallback = listener;
 this.downUrl = downUrl;
 }
 
 @Override
 public Response intercept(Chain chain) throws IOException {
 Response response = chain.proceed(chain.request());
 
 return response.newBuilder()
 .body(new DownloadResponseBody(response.body(), downFileCallback,downUrl))
 .build();
 }
}

然后我們的service

public interface HttpService {
 
 /*大文件需要加入Streaming這個(gè)判斷,防止下載過程中寫入到內(nèi)存中,造成oom*/
 @Streaming
 @GET
 Observable<ResponseBody> download(@Header("range") String start, @Url String url);
}

接下來我們的DownloadManager中download方法

 /**
 * 開始下載
 * @param url 下載地址
 * @param downFileCallback 進(jìn)度回調(diào)接口
 */
 public void download(final String url, final DownFileCallback downFileCallback) {
 /*正在下載不處理*/
 if (url == null || submap.get(url) != null) {
 return;
 }
 
 Downloadinterceptor interceptor = new Downloadinterceptor(downFileCallback, url);
 okHttpClient = new OkHttpClient.Builder()
 .addInterceptor(interceptor)
 .build();
 Retrofit retrofit = new Retrofit.Builder()
 .client(okHttpClient)
 .baseUrl("http://imtt.dd.qq.com")
 .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
 .build();
 final HttpService httpservice = retrofit.create(HttpService.class);
 
 ProgressDownSubscriber subscriber =
 Observable.just(url)
 .flatMap(new Function<String, ObservableSource<DownloadInfo>>() {
 @Override
 public ObservableSource<DownloadInfo> apply(String s) throws Exception {
 return Observable.just(createDownInfo(s));
 }
 })
 .map(new Function<DownloadInfo, DownloadInfo>() {
 @Override
 public DownloadInfo apply(DownloadInfo s) throws Exception {
 return getRealFileName(s);
 }
 })
 .flatMap(new Function<DownloadInfo, Observable<ResponseBody>>() {
 @Override
 public Observable<ResponseBody> apply(DownloadInfo downInfo) throws Exception {
 return httpservice.download("bytes=" + downInfo.getProgress() + "-", downInfo.getUrl());
 }
 })//下載
 .map(new Function<ResponseBody, DownloadInfo>() {
 @Override
 public DownloadInfo apply(ResponseBody responsebody) {
 try {
 return writecache(responsebody, url);
 } catch (IOException e) {
 //*失敗拋出異常*//
 e.printStackTrace();
 }
 return null;
 }
 })
 .observeOn(AndroidSchedulers.mainThread())//在主線程回調(diào)
 .subscribeOn(Schedulers.io())//在子線程執(zhí)行
 .subscribeWith(new ProgressDownSubscriber<DownloadInfo>() {
 @Override
 public void onNext(DownloadInfo downInfo) {
 downFileCallback.onSuccess(downInfo);
 submap.remove(downInfo.getUrl());
 }
 
 @Override
 public void onError(Throwable t) {
 downFileCallback.onFail(t.getMessage());
 submap.remove(url);
 }
 });
 
 
 submap.put(url, subscriber);
 }

然后暫停操作:

 /**
 * 暫停下載
 */
 public void stop(String url) {
 if (url == null) return;
 if (submap.containsKey(url)) {
 ProgressDownSubscriber subscriber = submap.get(url);
 subscriber.dispose();
 submap.remove(url);
 }
 }

從服務(wù)器獲取文件長度

/**
 * 從服務(wù)器獲取文件長度
 *
 * @param downloadUrl
 * @return
 */
 private long getContentLength(String downloadUrl) {
 Request request = new Request.Builder()
 .url(downloadUrl)
 .build();
 try {
 Response response = mClient.newCall(request).execute();
 if (response != null && response.isSuccessful()) {
 long contentLength = response.body().contentLength();
 response.close();
 return contentLength == 0 ? DownloadInfo.TOTAL_ERROR : contentLength;
 }
 } catch (IOException e) {
 e.printStackTrace();
 }
 return DownloadInfo.TOTAL_ERROR;
 }

從服務(wù)器獲取文件長度的時(shí)候注意一下,Android P之后,也就是api 28以上禁止明文網(wǎng)絡(luò)傳輸。需要在你的AndroidManifest中的application標(biāo)簽中聲明"android:usesCleartextTraffic="true",允許應(yīng)用進(jìn)行明文傳輸。

使用方法:首先要獲取sd卡權(quán)限

DownloadManager.getInstance().downloadPath(本地存放地址).download(url1, new DownFileCallback() {
 @Override
 public void onSuccess(DownloadInfo info) {
 
 Toast.makeText(MainActivity.this, url1 + "下載完成", Toast.LENGTH_SHORT).show();
 }
 
 @Override
 public void onFail(String msg) {
 Toast.makeText(MainActivity.this, url1 + "下載失敗", Toast.LENGTH_SHORT).show();
 }
 
 @Override
 public void onProgress(final long totalSize, final long downSize) {
 // 需要注意的是,如果文件總大小為50M,已下載的大小為10M,
 // 再次下載時(shí)onProgress返回的totalSize是文件總長度
 // 減去 已下載大小 10M, 即40M,downSize為本次下載的已下載量
 // 好消息是,我已經(jīng)在內(nèi)部做過處理,放心使用吧,但是這個(gè)問題大家還是要知道的
 
 runOnUiThread(new Runnable() {
 @Override
 public void run() {
 int progress = (int) (downSize * 100 / totalSize);
 progress1.setProgress(progress);
 }
 });
 }
 });

好了今天就到這里,希望能幫到大家,這對(duì)我來說也是一種加深印象的筆記。

demo下載地址

github地址:DownManager  歡迎star

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • IDEA修改SVN地址的實(shí)現(xiàn)

    IDEA修改SVN地址的實(shí)現(xiàn)

    如果你正在使用SVN進(jìn)行版本控制,并且需要更改你的SVN地址,那么這篇文章將為你提供必要的步驟和指導(dǎo),感興趣的可以了解一下
    2023-12-12
  • java實(shí)現(xiàn)輸出文件夾下某個(gè)格式的所有文件實(shí)例代碼

    java實(shí)現(xiàn)輸出文件夾下某個(gè)格式的所有文件實(shí)例代碼

    這篇文章主要介紹了java實(shí)現(xiàn)輸出文件夾下某個(gè)格式的所有文件,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-06-06
  • 如何使用pipeline和jacoco獲取自動(dòng)化測(cè)試代碼覆蓋率

    如何使用pipeline和jacoco獲取自動(dòng)化測(cè)試代碼覆蓋率

    這篇文章主要介紹了如何使用pipeline和jacoco獲取自動(dòng)化測(cè)試代碼覆蓋率,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 若依 MyBatis改為MyBatis-Plus的實(shí)現(xiàn)步驟

    若依 MyBatis改為MyBatis-Plus的實(shí)現(xiàn)步驟

    本文主要介紹了若依 MyBatis改為MyBatis-Plus的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • Java構(gòu)建對(duì)象常用3種方法解析

    Java構(gòu)建對(duì)象常用3種方法解析

    這篇文章主要介紹了Java構(gòu)建對(duì)象常用3種方法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • SpringBoot實(shí)現(xiàn)緩存組件配置動(dòng)態(tài)切換的步驟詳解

    SpringBoot實(shí)現(xiàn)緩存組件配置動(dòng)態(tài)切換的步驟詳解

    現(xiàn)在有多個(gè)springboot項(xiàng)目,但是不同的項(xiàng)目中使用的緩存組件是不一樣的,有的項(xiàng)目使用redis,有的項(xiàng)目使用ctgcache,現(xiàn)在需要用同一套代碼通過配置開關(guān),在不同的項(xiàng)目中切換這兩種緩存,本文介紹了SpringBoot實(shí)現(xiàn)緩存組件配置動(dòng)態(tài)切換的步驟,需要的朋友可以參考下
    2024-07-07
  • Java中默認(rèn)的訪問權(quán)限作用域解析

    Java中默認(rèn)的訪問權(quán)限作用域解析

    這篇文章主要介紹了Java中默認(rèn)的訪問權(quán)限作用域,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 快速搭建springboot項(xiàng)目(新手入門)

    快速搭建springboot項(xiàng)目(新手入門)

    本文主要介紹了快速搭建springboot項(xiàng)目(新手入門),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • 基于Mybatis Plus實(shí)現(xiàn)多表分頁查詢的示例代碼

    基于Mybatis Plus實(shí)現(xiàn)多表分頁查詢的示例代碼

    這篇文章主要介紹了基于Mybatis Plus實(shí)現(xiàn)多表分頁查詢的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • SparkStreaming整合Kafka過程詳解

    SparkStreaming整合Kafka過程詳解

    這篇文章主要介紹了SparkStreaming整合Kafka過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-01-01

最新評(píng)論

金秀| 巴中市| 昌江| 巴塘县| 中西区| 禄丰县| 四子王旗| 寻甸| 奉化市| 常宁市| 东兰县| 盱眙县| 自治县| 淮安市| 吉安市| 鹤山市| 高州市| 开封县| 海门市| 广平县| 汉阴县| 德钦县| 凤庆县| 青海省| 久治县| 黎平县| 宜川县| 大方县| 凌云县| 建瓯市| 内江市| 呼玛县| 宣化县| 拉萨市| 龙井市| 运城市| 钟山县| 绥化市| 文安县| 平顶山市| 石台县|