user1854307
user1854307

Reputation: 630

Android Observables.zip list observables

I need to execute several parallel requests to the server to retrieve data. How can I do this using observables. My implementation

public void get(String s, Observer<Boolean> observer) {
    APIService apiService = App.getApi();
    final Observable<User> oUser = apiService.getUser(Integer.valueOf(s));
    final Observable<List<DocType>> oDocType = apiService.getDocType();
    final Observable<List<TaskTypes>> oTaskTypes = apiService.getTaskType();
    final Observable<List<DocTaskLeave>> oTaskLeave = apiService.getTaskLeave();
    final Observable<List<DocStatus>> oDocStatus = apiService.getDocStatus();
    final Observable<List<DocPayment>> oDocPayment = apiService.getPaymentType();
    final Observable<List<DocCredit>> oDocCredit = apiService.getPaymentCredit();
    final Observable<List<ClientRegion>> oClientRegion = apiService.getClientRegion();
    final Observable<List<ProductRules>> oProductRules = apiService.getProductsRules();
    final Observable<List<ReportTypes>> oReportTypes = apiService.getReportType();
    List<Observable> observables = new ArrayList<>();
    observables.add(oUser);
    observables.add(oDocType);
    observables.add(oTaskTypes);
    observables.add(oTaskLeave);
    observables.add(oDocStatus);
    observables.add(oDocPayment);
    observables.add(oDocCredit);
    observables.add(oClientRegion);
    observables.add(oProductRules);
    observables.add(oReportTypes);
    Observable obs = Observable.zip(observables, new FuncN() {
        @Override
        public Object call(Object... args) {
            return null;
        }
    });
    obs.subscribe(observer);
}

I think that this is wrong because. IDE shows a warning. enter image description here

Upvotes: 2

Views: 625

Answers (1)

Maksim Ostrovidov
Maksim Ostrovidov

Reputation: 11058

The solution with zip would be ugly and verbose cause you have as many as 10 observables, each of different type. Also, you'll need to cast each result to its proper type before storing it into DB.

Since your goal is to fetch and store various pieces of data (as I can see), I would represent each task as a separate Completable that executes on its own Scheduler:

final Completable oUser = apiService.getUser(Integer.valueOf(s))
        .doOnNext(result -> /* save to db */) // or flatMap
        .toCompletable()
        .retry(3) // in case of upstream error - retries this task (up to 3 times)
        .onErrorComplete() // replaces upstream errors with onCompleted event
        .subscribeOn(Schedulers.io());

final Completable oDocType = apiService.getDocType()
        .doOnNext(result -> /* save to db */)
        .toCompletable()
        .retry(3)
        .onErrorComplete()
        .subscribeOn(Schedulers.io());

// ... etc

Completable.merge(oUser, oDocType, oTaskTypes, oTaskLeave, oDocStatus, 
        oDocPayment, oDocCredit, oClientRegion, oProductRules, oReportTypes)
            .subscribe(new CompletableSubscriber() {
                @Override
                public void onCompleted() {
                    // all done!
                }

                @Override
                public void onError(Throwable e) {
                    // handle error
                }

                @Override
                public void onSubscribe(Subscription d) {
                    // manage subscription if needed
                }
            });

All tasks execute in parallel. Also, you could set retry count for each request or any other additional logic.

Upvotes: 1

Related Questions