RxJava循环用于执行异步工作

时间:2017-10-09 20:52:00

标签: android rx-java rx-android rx-java2

我正在使用Compressor库,我想使用RxJava压缩图像。以下是图书馆文档中的示例。

new Compressor(this)
        .compressToFileAsFlowable(actualImage)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer<File>() {
            @Override
            public void accept(File file) {
                compressedImage = file;
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) {
                throwable.printStackTrace();
                showError(throwable.getMessage());
            }
        });

这非常有效。现在我想压缩一个图像列表,我如何使用这种技术来获取压缩文件路径列表?

我尝试在for循环中添加此方法但返回的列表为空,因为accept方法甚至没有调用一次,代码到达return语句。以下是我的方法

   @NonNull
    private ArrayList<String> compressFiles(ArrayList<String> files, File directory) {
        final ArrayList<String> filesToReturn = new ArrayList<>();
        for (final String filepath : files) {
            new Compressor(this)
                    .compressToFileAsFlowable(new File(filepath))
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<File>() {
                        @Override
                        public void accept(File file) {
                            filesToReturn.add(file.getAbsolutePath());
                        }
                    }, new Consumer<Throwable>() {
                        @Override
                        public void accept(Throwable throwable) {
                            throwable.printStackTrace();
                        }
                    });
        }
        return filesToReturn;
    }

如何使用RxJava更改此方法,因此只有在压缩所有文件并填充列表后才会触发accept方法?

我尝试搜索RxJava循环/ Flatmap但我无法弄清楚它们。我是RxJava的新手。任何帮助或指示都将受到高度赞赏。

2 个答案:

答案 0 :(得分:0)

在RxJava中,您将使用Observable.fromIterable():

Observable.fromIterable(files)
   .flatMapIterable(files -> files)
   .flatMap(filepath -> new Compressor(this).compressToFileAsFlowable(new File(filepath)))
   .subscribeOn(Schedulers.io())
   .observeOn(AndroidSchedulers.mainThread())
   .subscribe(new Consumer<File>() {
        @Override
        public void accept(File file) {
            compressedImage = file;
        }
   }, new Consumer<Throwable>() {
        @Override
        public void accept(Throwable throwable) {
            throwable.printStackTrace();
            showError(throwable.getMessage());
        }
   });

答案 1 :(得分:0)

以下是两个可能的结果:

  1. 处理完所有图像后,将调用Completable

  2. Flowable会在完成处理(荣誉背压)后将结果推送给订阅者

  3. 请查看subscribeOn。我使用计算调度程序,因为cpu绑定工作应该在有界线程池上执行。 IO是无限的。

    当您订阅Completeable或Flowable时,您必须将observeOn应用于Android-MainUI-Scheduler。

    Rember只有在状态改变时才能订阅Flowable / Observable。否则一起组成观察者。

    // Will call complete, when all files finish
    private Completable compressFiles(ArrayList<String> files) {
            return Flowable.fromIterable(files)
                    .subscribeOn(Schedulers.io())
                    .map(new Function<String, File>() {
                        @Override
                        public File apply(String s) throws Exception {
                            return Paths.get(s).toFile();
                        }
                    })
                    .flatMapCompletable(new Function<File, CompletableSource>() {
                        @Override
                        public CompletableSource apply(File file) throws Exception {
                            return new Compressor(appContext)
                                    .compressToFileAsFlowable(file)
                                    .singleOrError()
                                    .toCompletable();
                        }
                    });
        }
    
    
    // Will push each file to subscriber as one finishes
    private Flowable<File> compressFiles2(ArrayList<String> files) {
        return Flowable.fromIterable(files)
                .subscribeOn(Schedulers.io())
                .map(new Function<String, File>() {
                    @Override
                    public File apply(String s) throws Exception {
                        return Paths.get(s).toFile();
                    }
                })
                .flatMap(new Function<File, Publisher<? extends File>>() {
                    @Override
                    public Publisher<? extends File> apply(File file) throws Exception {
                        return new Compressor(appContext)
                                .compressToFileAsFlowable(file)
                                .subscribeOn(Schedulers.computation());
                    }
                });
    }