【问题标题】:RxAndroid download multiple files, max 3 concurrent threadRxAndroid下载多个文件,最多3个并发线程
【发布时间】:2016-11-17 14:49:57
【问题描述】:

我有 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()

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

【问题讨论】:

    标签: rx-java rx-android


    【解决方案1】:

    您可以使用 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 做了什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-13
      相关资源
      最近更新 更多