RxJava,Retrofit,Android-等待所有请求完成

时间:2020-07-02 11:46:19

标签: android retrofit rx-java

我有一种方法可以ping通名为computerItemList的列表中的所有计算机,并检查它是否在线。我想通过向API发送并行请求来做到这一点。下面的代码模拟了来自服务器的响应,并且正在运行,但是当所有请求完成解锁ping按钮时,我需要信息。怎么做? 通常,我要对列表中的所有项目执行异步命令,然后等待所有操作完成。

public void pingComputers() {
        for (ComputerItem computerItem : _computerItemList) {
            Observable.just(computerItem)
                    .subscribeOn(Schedulers.io())
                    .subscribe(item -> {
                        int sleepTime = randomizer.nextInt(1000) + 200;
                        int status = randomizer.nextInt(ComputerStatus.values().length - 1) + 1;

                        Log.d(TAG, Thread.currentThread().getName() + " >>pingSelected: " + item + " sleep: " + sleepTime);
                        Thread.sleep(sleepTime);
                        item.setStatus(ComputerStatus.values()[status]);

                        updateComputerList();
                    });
        }
    }

更新 我写了这样的东西。可以吗?

public void ping2() {
        Observable.fromIterable(_computerItemList)
                .flatMap(computerItem -> {
                    return Observable.just(computerItem)
                            .subscribeOn(Schedulers.io())
                            .map(item -> {
                                int sleepTime = randomizer.nextInt(1000) + 200;
                                Log.d(TAG, "ping2: Sleeping for " + sleepTime);
                                Thread.sleep(sleepTime);

                                int status = randomizer.nextInt(ComputerStatus.values().length - 1) + 1;
                                item.setStatus(ComputerStatus.values()[status]);

                                updateComputerList();
                                return item;
                            });
                }).doOnComplete(() -> Log.d(TAG, "ping2: COMPLETE")).subscribe();

    }

更新-它正在工作!但这可以吗?

public void executeCommand(CommandType command) {
        isWorking.setValue(true);
        
        Observable.fromIterable(_computerItemList)
                .subscribeOn(Schedulers.io())
                .flatMap(computerItem -> createPingObservable(computerItem))
                .observeOn(AndroidSchedulers.mainThread())
                .doOnComplete(() -> isWorking.setValue(false))
                .subscribe();
    }


private Observable<ComputerItem> createPingObservable(ComputerItem computerItem) {
        return Observable.just(computerItem)
                .subscribeOn(Schedulers.io())
                .map(item -> {
                    int sleepTime = randomizer.nextInt(1000) + 200;
                    int status = randomizer.nextInt(ComputerStatus.values().length - 1) + 1;

                    Log.d(TAG, Thread.currentThread().getName() + ">>> executeCommand: PING");
                    Thread.sleep(sleepTime);
                    item.setStatus(ComputerStatus.values()[status]);

                    updateComputerList();
                    return item;
                });
    }

1 个答案:

答案 0 :(得分:0)

更新-它正在工作!但这还可以吗?

否,以这种方式调用updateComputerList();是不可行的,您将不得不synchronized调用它,因为您将从多个线程中调用它,每个线程都试图改变状态。

我会这样:

Observable.fromIterable(list)
                    .flatMap(computerItem -> createPingObservable(computerItem))
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(computerItem -> updateComputerList(computerItem));
        }

另外,不要使用Thread.sleep(sleepTime);,只需使用

.delay(randomizer.nextInt(1000) + 200, TimeUnit.MILLISECONDS)