问题
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