首頁  >  文章  >  Java  >  RxJava2.x與ReTrofit2.x多執行緒如何下載檔案的實例

RxJava2.x與ReTrofit2.x多執行緒如何下載檔案的實例

黄舟
黄舟原創
2017-09-19 09:52:142390瀏覽

本篇文章主要介紹了RxJava2.x+ReTrofit2.x多執行緒下載檔案的範例程式碼,具有一定的參考價值,有興趣的可以了解

寫在前面:

接到公司需求:要做一個apk升級的功能,原理其實很簡單,百度也一大堆例子,可大部分都是用框架,要嘛就是HttpURLConnection,實在是不想這麼做。剛好看了兩天的RxJava2.x+ReTrofit2.x,據說這兩個框架是目前最熱門的非同步請求框架了。固本文使用RxJava2.x+ReTrofit2.x實作多執行緒下載檔案的功能。
如果對RxJava2.x+ReTrofit2.x不太了解的請先去看相關的文件。
大神至此請無視。

思路分析:

思路及其簡潔明了,主要分為以下四步驟

1.取得伺服器檔案大小.
2 .根據檔案大小規劃線程數量.
3.根據下載內容合併為完整文件.
4.調用安裝,安裝apk.
功能實現

來,接下來是你們最喜歡的擼程式碼環節

1.首先看引用


  compile 'io.reactivex:rxjava:latest.release'
  compile 'io.reactivex:rxandroid:latest.release'
  //network - squareup
  compile 'com.squareup.retrofit2:retrofit:latest.release'
  compile 'com.squareup.retrofit2:adapter-rxjava:latest.release'
  compile 'com.squareup.okhttp3:okhttp:latest.release'
  compile 'com.squareup.okhttp3:logging-interceptor:latest.release'

2.建構一個下載介面DownloadService.class


#
public interface DownloadService {
  @Streaming
  @GET
  //downParam下载参数,传下载区间使用
  //url 下载链接
  Observable<ResponseBody> download(@Header("RANGE") String downParam,@Url String url);
}

3.為了使用方便封裝了一個RetrofitHelper.class,主要用於:

a)實例化OkHttpClient和Retrofit.


#
  public RetrofitHelper(String url, DownloadProgressListener listener) {

    DownloadProgressInterceptor interceptor = new DownloadProgressInterceptor(listener);

    OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(interceptor)
        .retryOnConnectionFailure(true)
        .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
        .build();
    retrofit = new Retrofit.Builder()
        .baseUrl(url)
        .client(client)
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();
  }

b)封裝下載方法,本次下載我使用的是三個下載線程,並沒有動態分配,各位可以根據自己的需求去動態分配線程個數


 public Observable download(@NonNull final long start, @NonNull final long end, @NonNull final String url, final File file, final Subscriber subscriber) {
    String str = "";
    if (end == -1) {
      str = "";
    } else {
      str = end + "";
    }
    return retrofit.create(DownloadService.class).download("bytes=" + start + "-" + str, url).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).map(new Func1<ResponseBody, ResponseBody>() {
      @Override
      public ResponseBody call(ResponseBody responseBody) {
        return responseBody;
      }
    }).observeOn(Schedulers.computation()).doOnNext(new Action1<ResponseBody>() {
      @Override
      public void call(ResponseBody responseBody) {
        //第一次请求全部文件长度
        if (end == -1) {
          try {
            RandomAccessFile randomFile = new RandomAccessFile(file, "rw");
            randomFile.setLength(responseBody.contentLength());
            long one = responseBody.contentLength() / 3;
            download(0, one, url, file, subscriber).mergeWith(download(one, one * 2, url, file, subscriber)).mergeWith(download(one * 2, responseBody.contentLength(), url, file, subscriber)).subscribe(subscriber);

          } catch (IOException e) {
            e.printStackTrace();
          }
        } else {
          FileUtils fileUtils = new FileUtils();
          fileUtils.writeFile(start, end, responseBody.byteStream(), file);
        }

      }
    }).subscribeOn(AndroidSchedulers.mainThread());
  }

 4.呼叫下載

註:呼叫下載在MainAcitivity中進行,為了直觀我們封裝了進度攔截器以方便實現進度顯示,但是本篇不在敘述進度攔截器的實現過程,如有需要可以留言。

a)實作監聽物件


subscriber = new Subscriber() {
      @Override
      public void onCompleted() {
        Log.e("MainActivity", "onCompleted下下载完成");
//        Toast.makeText(MainActivity.this, "onCompleted下下载完成", Toast.LENGTH_LONG).show();
        installAPK("mnt/sdcard/aaaaaaaaa.apk");
      }

      @Override
      public void onError(Throwable e) {
        e.printStackTrace();
        Log.e("MainActivity", "onError: " + e.getMessage());
      }

      @Override
      public void onNext(Object o) {

      }
    };

 b)呼叫封裝的RetrofitHelper實作下載


 RetrofitHelper RetrofitHelper = new RetrofitHelper("http://gdown.baidu.com/data/wisegame/0904344dee4a2d92/", new DownloadProgressListener() {
      @Override
      public void update(long bytesRead, long contentLength, boolean done) {

        SharedPF.getSharder().setLong("update", bytesRead);
        pro.setProgress((int) ((double) bytesRead / contentLength * 100));
        temp++;
        if (temp <= 1) {
          Log.e("MainActivity", "update" + bytesRead + "");
        }
      }
    });
    RetrofitHelper.download(0, -1, "QQ_718.apk", new File("mnt/sdcard/", "aaaaaaaaa.apk"), subscriber).subscribe(new Subscriber() {
      @Override
      public void onCompleted() {

      }

      @Override
      public void onError(Throwable e) {

      }

      @Override
      public void onNext(Object o) {

      }
    });

  }

 註:最後貼上一個apk安裝的方法


  // 安装APK
  public void installAPK(String filePath) {
    Intent intent = new Intent();
    intent.setAction("android.intent.action.VIEW");
    intent.addCategory("android.intent.category.DEFAULT");
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// 广播里面操作需要加上这句,存在于一个独立的栈里
    intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive");
    mainActivity.startActivity(intent);
  }

以上是RxJava2.x與ReTrofit2.x多執行緒如何下載檔案的實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn