简体   繁体   中英

RxJava - zip list of Observable

I have a list of Observables (RxJava 1).

List<Observable> observableList = new ArrayList<>();

It can contain at least 1 Observable. Each has the same type of the result.

How can I zip results of the all Observables?

I thought about zip-operator but it doesn't support List and I don't know quantity of observables (it can be 1,2,3,4....)

You can use the static zip(java.lang.Iterable<? extends Observable<?>> ws,FuncN<? extends R> zipFunction) method .

It is a zip method that takes an Iterable of Observable s and a FuncN (which takes a varargs parameter for its call method) and uses it to combine the corresponding emitted Object s into the result to be omitted by the new returned Observable .

So for example you could do:

Observable.zip(observableList, new FuncN(){
    public ReturnType call(java.lang.Object... args){
        ReturnType result; //to be made
        //preparatory code for using the args
        for (Object obj : args){
            ReturnType retObj = (ReturnType)obj;
            //code to use the arg once at a time to combine N of them into one.
        }
        return result;
    }
});

ReactiveX - Zip operator

Zip beyond BiFunction

Zip combine the emissions of multiple Observables together via a specified function and emit single items for each combination based on the results of this function

Here, list is an Array List of Observables of whichever type you want to pass.

val list = arrayListOf<Observable<ImageUrlResponse>>()


Observable.zip(list) { args -> Arrays.asList(args) }
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({
        val response = it[0]
        val imageUrlResponse = imageUrlObject as ImageUrlResponse
        urls.add(imageUrlResponse.imageUrl)}
               }, {
        val c = it
 })

The Result of the following subscription is this image below. Just like we expect it to be zipped together . Also can you notice it returns all the responses to be zipped in a single java.lang.Object[] .

Note I had to type cast my Array List to access my single object because it is of type Any!

在此处输入图片说明

I struggled with this as well, and used Sharan's solution as a base for mine.

My use case was doing API calls to several 3rd party providers, and then putting each individual result in a List. Each item in the list contains what the API returned, be it success or failure.

In the end it actually looks quite elegant. In my specific case "ResultType" was replaced with something like "ApiGenericResponseObject".

Observable.zip(listOfObservables, args -> {
    List<ResultType> result = new ArrayList<>();
    for (Object o: args) {
        ResultType c = (ResultType) o;
        // additional code here, I am just concatenating them together
        // This gives me a list with the individual result of each Observable (for instance an API call)
        result.add(c);
    }
    return result;
});

Alternatively, as a Lambda it looks neater. Though I wonder whether someone reading this will understand what is going on:

Observable.zip(listOfObservables, args -> Arrays.stream(args)
    .map(object -> (ResultType) object)
    .collect(Collectors.toList())
);

Hope it helps!

You can .stream and .reduce your List before .zip -ping it:

final Observable<YourType> result = observableList.stream()
        .reduce((observable1, observable2) ->
                Observable.zip(observable1, observable2, YourTypeCombiner::methodToCombineTwoObjectsOfYourType))
        .orElse(Observable.just(defaultValueForYourType));

eg result will emit new Integer(10)

final List<Observable<Integer>> observableList = ImmutableList.of(
        Observable.just(1), Observable.just(2), Observable.just(3), Observable.just(4));

final Observable<Integer> result = observableList.stream()
        .reduce((num1, observable2) ->
                Observable.zip(observable1, observable2, Integer::sum))
        .orElse(Observable.just(0));

Error-handling not included.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM