RXJava. Identify when all obervables inside for loop are finished

房东的猫 提交于 2021-02-08 07:41:07

问题


I want to perform the following. I have a list of transactions which i want to update by making 2 api requests (i am using retrofit2), for each transactions and then saving the result into a database(using the observer). After some searching i decided to use zip operator to combine the 2 requests but the issue that i'm have is that i cannot identify when the whole process is finished to update the UI. Code looks like this.

for (Transaction realmTransaction : allTransactions) {

        Observable<Map<String, String>> obs1 = getObs1(realmTransaction);

        Observable<Map<String, String>> obs2= getObs2(realmTransaction);

       Observable.zip(obs1, obs2,
                (map1, map2) -> {
                    Map<String, String> combined = new HashMap<>();
// do some processing and return a single map after 
                    return combined;
                })
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(getObserver(realmTransaction));
    }

public Observer<Map<String, String>> getObserver(Transaction t){
return new Observer<Map<String, String>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Map<String, String> stringStringMap) {
// update database
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                }
}

The observer that i have updates a field of the realmTransaction object.

My question is how do i get notified when the for loop has ended??

I would like to sent an event (maybe use EventBust) after the whole process has finish to kick off some other method.

Thanks

Also another small question that i have is about the function that i provide inside the zip operator, how can i specify on which thread that function will run on? I would like to use a computation thread for that thats why i put observeOn twice, but I couldnt find an answer anywhere


回答1:


Whenever you have a for loop, you should think about range, fromArray or fromIterable. In addition, you may not need the full subscribe but doOnNext():

Observable.fromIterable(allTransactions)
    .flatMap(realmTransaction -> {
        Observable<Map<String, String>> obs1 = getObs1(realmTransaction);

        Observable<Map<String, String>> obs2= getObs2(realmTransaction);

        return Observable.zip(obs1, obs2, (map1, map2) -> {
            Map<String, String> combined = new HashMap<>();
            // do some processing and return a single map after 
            return combined;
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnNext(stringStringMap -> handle(stringStringMap, realmTransaction));
   })
   .ignoreElements()
   .subscribe(() -> handleCompleted(), e -> handleError(e));



回答2:


Since every thing is being done asynchronously , you can create a local variable outside the loop,say count and and keep incrementing it getObserver function and later check the count is equal to the length of allTransactions. And about your second question, I think the subscribe thread will be used. You using the 2 subscribeOn, only last one will be used.



来源:https://stackoverflow.com/questions/48736411/rxjava-identify-when-all-obervables-inside-for-loop-are-finished

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