RxAndroid download multiple files, max 3 concurrent thread

此生再无相见时 提交于 2020-06-27 04:04:29

问题


I have api to download single mp3 file from server,which is consumed using RxJava as bellow.

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

This just downloads single file , callback saves the file on disk. I want to download list of files save each file on disk and wait till all download completes , At max 3 calls should be executing in parallel. How to do it with RXAndroid , I tried flatmap but i am not able to understand it fully.

EDIT New Code

 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) {
                }
            });

this is working fine but when network is down or slow internet connection i am getting

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

I am unable to understand which thread exactly need to observeOn() android main thread.


回答1:


You can achieve this with flatMap, limiting its concurrency, but also need an inner Observable running on a background scheduler that does the file transfer:

 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.*/ });

Edit:

Since you are using an Observable API for the network download, you don't need to block:

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

It is unclear though what you do with CallBackWithErrorHandling.



来源:https://stackoverflow.com/questions/40657957/rxandroid-download-multiple-files-max-3-concurrent-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!