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

Retrofit+RxJava實(shí)現(xiàn)帶進(jìn)度下載文件

 更新時(shí)間:2018年05月10日 08:34:50   作者:jiashuai94  
這篇文章主要為大家詳細(xì)介紹了Retrofit+RxJava實(shí)現(xiàn)帶進(jìn)度下載文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

Retrofit+RxJava已經(jīng)是目前市場(chǎng)上最主流的網(wǎng)絡(luò)框架,使用它進(jìn)行平常的網(wǎng)絡(luò)請(qǐng)求異常輕松,之前也用Retrofit做過(guò)上傳文件和下載文件,但發(fā)現(xiàn):使用Retrofit做下載默認(rèn)是不支持進(jìn)度回調(diào)的,但產(chǎn)品大大要求下載文件時(shí)顯示下載進(jìn)度,那就不得不深究下了。

接下來(lái)我們一起封裝,使用Retrofit+RxJava實(shí)現(xiàn)帶進(jìn)度下載文件。

github:JsDownload

先來(lái)看看UML圖:

大家可能還不太清楚具體是怎么處理的,別急,我們一步步來(lái):

1、添依賴是必須的啦

compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'

使用時(shí)注意版本號(hào)

2、寫(xiě)回調(diào)

/**
 * Description: 下載進(jìn)度回調(diào)
 * Created by jia on 2017/11/30.
 * 人之所以能,是相信能
 */
public interface JsDownloadListener {

 void onStartDownload();

 void onProgress(int progress);

 void onFinishDownload();

 void onFail(String errorInfo);

}

這里就不用多說(shuō)了,下載的回調(diào),就至少應(yīng)該有開(kāi)始下載、下載進(jìn)度、下載完成、下載失敗 四個(gè)回調(diào)方法。

注意下在onProgress方法中返回進(jìn)度百分比,在onFail中返回失敗原因。

3、重寫(xiě)ResponseBody,計(jì)算下載百分比

/**
 * Description: 帶進(jìn)度 下載請(qǐng)求體
 * Created by jia on 2017/11/30.
 * 人之所以能,是相信能
 */
public class JsResponseBody extends ResponseBody {

 private ResponseBody responseBody;

 private JsDownloadListener downloadListener;

 // BufferedSource 是okio庫(kù)中的輸入流,這里就當(dāng)作inputStream來(lái)使用。
 private BufferedSource bufferedSource;

 public JsResponseBody(ResponseBody responseBody, JsDownloadListener downloadListener) {
 this.responseBody = responseBody;
 this.downloadListener = downloadListener;
 }

 @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);
 // read() returns the number of bytes read, or -1 if this source is exhausted.
 totalBytesRead += bytesRead != -1 ? bytesRead : 0;
 Log.e("download", "read: "+ (int) (totalBytesRead * 100 / responseBody.contentLength()));
 if (null != downloadListener) {
  if (bytesRead != -1) {
  downloadListener.onProgress((int) (totalBytesRead * 100 / responseBody.contentLength()));
  }

 }
 return bytesRead;
 }
 };

 }
}

將網(wǎng)絡(luò)請(qǐng)求的ResponseBody 和JsDownloadListener 在構(gòu)造中傳入。

這里的核心是source方法,返回ForwardingSource對(duì)象,其中我們重寫(xiě)其read方法,在read方法中計(jì)算百分比,并將其傳給回調(diào)downloadListener。

4、攔截器

只封裝ResponseBody 是不夠的,關(guān)鍵我們需要拿到請(qǐng)求的ResponseBody ,這里我們就用到了攔截器Interceptor 。

/**
 * Description: 帶進(jìn)度 下載 攔截器
 * Created by jia on 2017/11/30.
 * 人之所以能,是相信能
 */
public class JsDownloadInterceptor implements Interceptor {

 private JsDownloadListener downloadListener;

 public JsDownloadInterceptor(JsDownloadListener downloadListener) {
 this.downloadListener = downloadListener;
 }

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

通常情況下攔截器用來(lái)添加,移除或者轉(zhuǎn)換請(qǐng)求或者回應(yīng)的頭部信息。

在攔截方法intercept中返回我們剛剛封裝的ResponseBody 。

5、網(wǎng)絡(luò)請(qǐng)求service

/**
 * Description:
 * Created by jia on 2017/11/30.
 * 人之所以能,是相信能
 */
public interface DownloadService {

 @Streaming
 @GET
 Observable<ResponseBody> download(@Url String url);

}

注意:

這里@Url是傳入完整的的下載URL;不用截取
使用@Streaming注解方法

6、最后開(kāi)始請(qǐng)求

/**
 1. Description: 下載工具類(lèi)
 2. Created by jia on 2017/11/30.
 3. 人之所以能,是相信能
 */
public class DownloadUtils {

 private static final String TAG = "DownloadUtils";

 private static final int DEFAULT_TIMEOUT = 15;

 private Retrofit retrofit;

 private JsDownloadListener listener;

 private String baseUrl;

 private String downloadUrl;

 public DownloadUtils(String baseUrl, JsDownloadListener listener) {

 this.baseUrl = baseUrl;
 this.listener = listener;

 JsDownloadInterceptor mInterceptor = new JsDownloadInterceptor(listener);

 OkHttpClient httpClient = new OkHttpClient.Builder()
 .addInterceptor(mInterceptor)
 .retryOnConnectionFailure(true)
 .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
 .build();

 retrofit = new Retrofit.Builder()
 .baseUrl(baseUrl)
 .client(httpClient)
 .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
 .build();
 }

 /**
 * 開(kāi)始下載
 *
 * @param url
 * @param filePath
 * @param subscriber
 */
 public void download(@NonNull String url, final String filePath, Subscriber subscriber) {

 listener.onStartDownload();

 // subscribeOn()改變調(diào)用它之前代碼的線程
 // observeOn()改變調(diào)用它之后代碼的線程
 retrofit.create(DownloadService.class)
 .download(url)
 .subscribeOn(Schedulers.io())
 .unsubscribeOn(Schedulers.io())
 .map(new Func1<ResponseBody, InputStream>() {

  @Override
  public InputStream call(ResponseBody responseBody) {
  return responseBody.byteStream();
  }
 })
 .observeOn(Schedulers.computation()) // 用于計(jì)算任務(wù)
 .doOnNext(new Action1<InputStream>() {
  @Override
  public void call(InputStream inputStream) {

  writeFile(inputStream, filePath);

  }
 })
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(subscriber);

 }

 /**
 * 將輸入流寫(xiě)入文件
 *
 * @param inputString
 * @param filePath
 */
 private void writeFile(InputStream inputString, String filePath) {

 File file = new File(filePath);
 if (file.exists()) {
 file.delete();
 }

 FileOutputStream fos = null;
 try {
 fos = new FileOutputStream(file);

 byte[] b = new byte[1024];

 int len;
 while ((len = inputString.read(b)) != -1) {
 fos.write(b,0,len);
 }
 inputString.close();
 fos.close();

 } catch (FileNotFoundException e) {
 listener.onFail("FileNotFoundException");
 } catch (IOException e) {
 listener.onFail("IOException");
 }

 }
}
  • 在構(gòu)造中將下載地址和最后回調(diào)傳入,當(dāng)然,也可以將保存地址傳入;
  • 在OkHttpClient添加我們自定義的攔截器;
  • 注意.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 支持RxJava;
  • 使用RxJava的map方法將responseBody轉(zhuǎn)為輸入流;
  • 在doOnNext中將輸入流寫(xiě)入文件;

當(dāng)然也需要注意下載回調(diào)的各個(gè)位置。

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

相關(guān)文章

  • Java微信公眾平臺(tái)開(kāi)發(fā)(7) 公眾平臺(tái)測(cè)試帳號(hào)的申請(qǐng)

    Java微信公眾平臺(tái)開(kāi)發(fā)(7) 公眾平臺(tái)測(cè)試帳號(hào)的申請(qǐng)

    這篇文章主要為大家詳細(xì)介紹了Java微信公眾平臺(tái)開(kāi)發(fā)第七步,微信公眾平臺(tái)測(cè)試帳號(hào)的申請(qǐng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Maven?Repository?使用方法

    Maven?Repository?使用方法

    對(duì)于Java開(kāi)發(fā)者來(lái)說(shuō),Maven?Repository是個(gè)必須掌握的網(wǎng)站,它可以讓開(kāi)發(fā)者更加方便地管理和維護(hù)?Java?項(xiàng)目的依賴項(xiàng),同時(shí)簡(jiǎn)化了項(xiàng)目開(kāi)發(fā)的過(guò)程,這篇文章主要介紹了Maven?Repository?使用方法,需要的朋友可以參考下
    2024-02-02
  • SpringBoot 對(duì)象存儲(chǔ) MinIO的詳細(xì)過(guò)程

    SpringBoot 對(duì)象存儲(chǔ) MinIO的詳細(xì)過(guò)程

    MinIO 是一個(gè)基于 Go 實(shí)現(xiàn)的高性能、兼容 S3 協(xié)議的對(duì)象存儲(chǔ),它適合存儲(chǔ)海量的非結(jié)構(gòu)化的數(shù)據(jù),這篇文章主要介紹了SpringBoot 對(duì)象存儲(chǔ) MinIO,需要的朋友可以參考下
    2023-07-07
  • kafka 啟動(dòng)報(bào)錯(cuò) missingTopicsFatal is true的解決

    kafka 啟動(dòng)報(bào)錯(cuò) missingTopicsFatal is true的解決

    這篇文章主要介紹了kafka 啟動(dòng)報(bào)錯(cuò) missingTopicsFatal is true的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 解決idea 通過(guò)build project 手動(dòng)觸發(fā)熱部署失敗的問(wèn)題

    解決idea 通過(guò)build project 手動(dòng)觸發(fā)熱部署失敗的問(wèn)題

    在debug運(yùn)行項(xiàng)目的過(guò)程中,并且保證(不添加方法,不修改方法名)一定的規(guī)則的情況下,可以通過(guò)build project 來(lái)手動(dòng)熱部署項(xiàng)目,本文給大家介紹解決idea 通過(guò)build project 手動(dòng)觸發(fā)熱部署失敗的問(wèn)題,感興趣的朋友一起看看吧
    2023-12-12
  • Springboot MultipartFile文件上傳與下載的實(shí)現(xiàn)示例

    Springboot MultipartFile文件上傳與下載的實(shí)現(xiàn)示例

    在Spring Boot項(xiàng)目中,可以使用MultipartFile類(lèi)來(lái)處理文件上傳和下載操作,本文就詳細(xì)介紹了如何使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-08-08
  • Spring通過(guò)c3p0配置bean連接數(shù)據(jù)庫(kù)

    Spring通過(guò)c3p0配置bean連接數(shù)據(jù)庫(kù)

    這篇文章主要為大家詳細(xì)介紹了Spring通過(guò)c3p0配置bean連接數(shù)據(jù)庫(kù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • 如何使用cmd命令行窗口運(yùn)行java文件

    如何使用cmd命令行窗口運(yùn)行java文件

    多年以來(lái)一直使用的是IDE來(lái)寫(xiě)java項(xiàng)目,導(dǎo)致很多的最基礎(chǔ)的東西都漸漸模糊了,最近遇到一個(gè)問(wèn)題就是如果命令行來(lái)運(yùn)行一個(gè)java項(xiàng)目,這里總結(jié)下,這篇文章主要給大家介紹了關(guān)于如何使用cmd命令行窗口運(yùn)行java文件的相關(guān)資料,需要的朋友可以參考下
    2023-10-10
  • Java中Arrays.sort()方法的比較器詳解

    Java中Arrays.sort()方法的比較器詳解

    這篇文章主要介紹了Java中Arrays.sort()方法的比較器詳解,Arrays.sort(Object[] a)此方法看似沒(méi)有要求我們實(shí)現(xiàn)比較器,對(duì)于基本數(shù)據(jù)類(lèi)型,String類(lèi)型確實(shí)如此,因?yàn)檫@些類(lèi)型中已經(jīng)自帶了compareTo()方法,需要的朋友可以參考下
    2023-12-12
  • 怎樣給Kafka新增分區(qū)

    怎樣給Kafka新增分區(qū)

    這篇文章主要介紹了怎樣給Kafka新增分區(qū)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評(píng)論

华阴市| 闽清县| 三原县| 绥芬河市| 伊春市| 鄂伦春自治旗| 固原市| 新源县| 介休市| 双城市| 保定市| 个旧市| 察隅县| 余江县| 东至县| 巴林左旗| 深州市| 历史| 青岛市| 综艺| 德州市| 吉安市| 满洲里市| 当雄县| 颍上县| 民和| 江安县| 牡丹江市| 星座| 鄢陵县| 富平县| 龙泉市| 榕江县| 宁海县| 化州市| 安溪县| 秭归县| 南昌县| 云阳县| 德钦县| 和顺县|