RxAndroid下载多个文件,最多3个并发线程

时间:2016-11-17 14:49:57

标签: rx-java rx-android

我有api从服务器下载单个mp3文件,使用下面的RxJava消费。

Observable<ResponseBody> observable = audioService.getFile(fileNameWithExtension);
        observable.subscribeOn(Schedulers.newThread())
                .observeOn(Schedulers.newThread())
                .subscribe(someCallBackClass<ResponseBody>);

这只是下载单个文件,回调将文件保存在磁盘上。 我想下载保存磁盘上每个文件的文件列表,并等到所有下载完成,最多3个调用应该并行执行。 如何使用RXAndroid,我尝试了flatmap但我无法完全理解它。

编辑新代码

 List<Observable<Response<ResponseBody>>> audioFiles = new ArrayList<>();

    for (String fileNameWithExtension : fileNamesWithExtension) {
        Observable<Response<ResponseBody>> observable = restFactory.getAudioService().getFile(fileNameWithExtension);
        audioFiles.add(observable);
    }

    Observable.from(audioFiles).flatMap(audioFile -> Observable.fromCallable(() -> {
        audioFile.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .toBlocking()
                .subscribe(new CallBackWithErrorHandling<>(Downloader.this));
        return 0;
    }).subscribeOn(Schedulers.io()), MAX_CONCURRENT)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Integer>() {
                @Override
                public void onCompleted() {
                   goToMainActivity();
                }

                @Override
                public void onError(Throwable e) {
                    Log.e(TAG, "Something went wrong , " + Thread.currentThread().getName());
                    Log.e(TAG, "Something went wrong , " + e.toString());
                    showToast(R.string.something_went_wrong);
                    goToMainActivity();
                }

                @Override
                public void onNext(Integer integer) {
                }
            });

这工作正常,但是当网络中断或互联网连接缓慢时,我正在

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

我无法理解thinkOn()android主线程究竟需要哪个线程。

1 个答案:

答案 0 :(得分:3)

您可以使用flatMap实现此目的,限制其并发性,但还需要在执行文件传输的后台调度程序上运行内部Observable:

 fileNames
 .flatMap(name -> {
      return Observable.fromCallable(() -> {
          // put your blocking download code here, save the data
          return name; // return what you need down below
      })
      .subscribeOn(Schedulers.io());
 }, 3)
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(completedFile -> { }, error -> { }, 
      () -> { /* all completed.*/ });

修改

由于您使用Observable API进行网络下载,因此您无需阻止:

Observable.from(audioFiles)
.flatMap(audioFile -> 
     audioFile.subscribeOn(Schedulers.io()),  // <-- apply extra transforms here
     MAX_CONCURRENT)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(completedFile -> { }, error -> { }, 
    () -> { /* all completed.*/ })

目前还不清楚你对CallBackWithErrorHandling做了什么。