Kordova
Kordova

Reputation: 73

Chain methods on rxjava

How to call a method after realizing all other methods have been done. all the methods are having observables.

Observable.just(""
    )
            .subscribe(new Subscriber<String>() {
        @Override
        public void onCompleted() {
            Log.d(TAG, "onCompleted: loading config");
            loadConfiguration();

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onNext(String s) {
            Log.d(TAG, "onNext: loading data");
            initOperatorData();
            initCompanyData();
            initVehicleData();
            initToolsData();
        }
    });

private void initCompanyData() {
    Subscription subscription = db.loadDataMaster()
            .map(new Func1<RealmResults<DataMaster>, List<String>>() {
                @Override
                public List<String> call(RealmResults<DataMaster> dataMasters) {
                    List<String> companies = getCompanyNames(dataMasters);
                    return companies;
                }
            })
            .subscribe(new Action1<List<String>>() {
                @Override
                public void call(List<String> companyNames) {
                    setCompanyNames(companyNames);
                }
            });}

I want to call the observables on those methods on "onNext" once they all finish, I call the one in onComplete. but this does not happen because they all async. onComplete happens before initToolsData.

Is there a way to chain calls to methods asynchronously?

Upvotes: 0

Views: 553

Answers (2)

Tassos Bassoukos
Tassos Bassoukos

Reputation: 16152

Let's try to simplify (and excuse the Java 8, it makes logic much more reasonable):

Observable.merge(
        initOperatorData().subscribeOn(Schedulers.io()),
        initCompanyData() .subscribeOn(Schedulers.io()),
        initVehicleData() .subscribeOn(Schedulers.io()),
        initToolsData()   .subscribeOn(Schedulers.io()))
.ignoreElements()
.doOnComplete(() -> loadConfiguration())
.toBlocking()
.subscribe();

private Observable<?> initCompanyData() {
    return db
        .loadDataMaster()
        .doOnNext(dataMasters -> setCompanyNames(getCompanyNames(dataMasters)));
}

Much more comprehensible, don't you say? BTW, if you don't need to wait for completion of the loadConfiguration() method, you can omit the .toBlocking() call. Also, you should use the computation() scheduler if you intend to run this on phones with less than 4 cores.

Upvotes: 0

dwursteisen
dwursteisen

Reputation: 11515

I assume that all your init* and loadConfiguration methods return Observable.

In this case, you can merge all Oservable then concatWith your another Observable, created from loadConfiguration

 Observable.merge(initOperatorData(), initCompanyData(), initVehicleData(), initToolsData())
           // I force to cast to Object otherwise, it may not compile, dependings of your methods signatures
           .cast(Object.class)
           // you'll subscribe to loadConfiguration when all previous Observable will be completed
           .concatwith(loadConfiguration())
           .subscribe();

Upvotes: 1

Related Questions