ホームページ  >  記事  >  Java  >  RxJava2.x および ReTrofit2.x マルチスレッドでファイルをダウンロードする方法の例

RxJava2.x および ReTrofit2.x マルチスレッドでファイルをダウンロードする方法の例

黄舟
黄舟オリジナル
2017-09-19 09:52:142390ブラウズ

この記事では主に RxJava2 のサンプル コードを紹介します。apk アップグレード機能を作成する原理は実際には非常に簡単です。Baidu にも多くの例がありますが、そのほとんどはフレームワークまたは HttpURLConnection を使用します。 。 RxJava2.x+ReTrofit2.x を 2 日間見てきました。現在、この 2 つのフレームワークが最も人気のある非同期リクエスト フレームワークであると言われています。この記事では、RxJava2.x+ReTrofit2.xを使用して、マルチスレッドのファイルダウンロード機能を実装します。

RxJava2.x+ReTrofit2.x についてよく知らない場合は、まず関連ドキュメントを読んでください。

マスター、これは無視してください。

アイデアの分析:



このアイデアは非常に簡潔かつ明確であり、主に次の 4 つのステップに分かれています

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) ダウンロード メソッドをカプセル化し、私はこのダウンロードを使用しました。3 つのダウンロード スレッドの動的割り当てはありません。必要に応じてスレッドの数を動的に割り当てることができます

 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. ダウンロードを呼び出します

注:ダウンロードは MainActivity で実行されます。直感的に理解できるように、進行状況の表示を容易にするために進行状況インターセプターをカプセル化しました。ただし、この記事では進行状況インターセプターの実装プロセスについては説明しません。必要に応じて、メッセージを残すことができます。

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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。