3

I have a varying length of Observable array. I would like to zip the requests (i.e. make a bunch of API requests and wait until all of them finish), but I cannot figure out how to implement the zip function.

Observable.zip(observables, new FuncN<List<ResponseBody>>() {
    @Override
    public List<ResponseBody> call(Object... args) {
        return Arrays.asList(args); <- compile error here
    }
});

Here the obserables is an array of List<Observable<ResponseBody>> and its length is unknown apriori.

The parameter of call in zip function cannot be corrected to ResponseBody.... How to make it return Observable<List<ResponseBody>>?

Is it a constraint in the design of FuncN RxJava 1.x.x?

P.S. I am using RxJava 1.1.6.

akarnokd
  • 69,132
  • 14
  • 157
  • 192
chubao
  • 5,871
  • 6
  • 39
  • 64
  • what is the problem exactly? the returned Type of FuncN method is the type of items that will be emitted by the created operator using the zip method, meaning here you'll have Observable> – yosriz Feb 23 '17 at 11:16
  • 1
    @yosriz, the problem is `Arrays.asList(args)` is not of `List` type, and it leads to compilation error. – chubao Feb 23 '17 at 12:34

3 Answers3

3

Just merge your observables and collect results using toList:

Observable.merge(observables).toList()
Maksim Ostrovidov
  • 10,720
  • 8
  • 42
  • 57
  • May I know if `merge` operation would block each request? I wish to fire the requests async at the same time, so that the requests will not block each other. – chubao Feb 23 '17 at 12:30
  • 1
    `merge` won't block, but `Observable.concat` will – Maksim Ostrovidov Feb 23 '17 at 12:36
  • I just have a try, I found the requests are being sent one by one, i.e. only the first request's had response before the 2nd request is being fired... – chubao Feb 24 '17 at 02:49
  • Did you mean you get this order: `1st request, 1st response, 2nd request, 2nd response, 3rd request, 3rd response`...? – Maksim Ostrovidov Feb 24 '17 at 03:23
  • Yes, I get this order when I use merge. – chubao Feb 24 '17 at 03:24
  • It's expected when there is no delay between subscription and result delivery. A result delivers faster than next Observable starts. But if you'll test with a delay on each Observable everything will fall into place. – Maksim Ostrovidov Feb 24 '17 at 03:49
0

I confirm merge operator works and find the culprit which causes the order: 1st request, 1st response, 2nd request, 2nd response, 3rd request, 3rd response.

The observable in observables list is not subscribed on Scheduler.io() during adding.

Previously:

observables.add(mViewModelDelegate.get().getApiService()
                    .rxGetCategoryBrandList(baseUrl, categoryId));

After:

observables.add(mViewModelDelegate.get().getApiService()
                    .rxGetCategoryBrandList(baseUrl, categoryId)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread());
chubao
  • 5,871
  • 6
  • 39
  • 64
0

User merge and make sure all observable requests have their own thread. You can try this:

private void runMyTest() {
    List<Single<String>> singleObservableList = new ArrayList<>();
    singleObservableList.add(getSingleObservable(500, "AAA"));
    singleObservableList.add(getSingleObservable(300, "BBB"));
    singleObservableList.add(getSingleObservable(100, "CCC"));
    Single.merge(singleObservableList)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(System.out::println);
}

private Single<String> getSingleObservable(long waitMilliSeconds, String name) {
    return Single
            .create((SingleOnSubscribe<String>) e -> {
                    try {
                        Thread.sleep(waitMilliSeconds);
                    } catch (InterruptedException exception) {
                        exception.printStackTrace();
                    }
                    System.out.println("name = " +name+ ", waitMilliSeconds = " +waitMilliSeconds+ ", thread name = " +Thread.currentThread().getName()+ ", id =" +Thread.currentThread().getId());
                    if(!e.isDisposed()) e.onSuccess(name);
                })
            .subscribeOn(Schedulers.io());
}

Output:

System.out: name = CCC, waitMilliSeconds = 100, thread name = RxCachedThreadScheduler-4, id =463

System.out: CCC

System.out: name = BBB, waitMilliSeconds = 300, thread name = RxCachedThreadScheduler-3, id =462

System.out: BBB

System.out: name = AAA, waitMilliSeconds = 500, thread name = RxCachedThreadScheduler-2, id =461

System.out: AAA

Bin Fan
  • 51
  • 6