Search code examples
methodsblockrx-java2

Blocking method execution until asynchronous RxJava call returns


I am pretty sure someone must have asked this question before but I cannot find it. I am trying to do something quite simple even for a RxJava beginner like me. I have the following method:

 public ILocation findLocationDetails() {
    requestLocationDetails();
    return buildLocationFromDetails();
}

The method requestLocationDetails contains a REST call which is executed inside another thread:

private void requestLocationDetails() {
    compositeDisposable.add(
        Observable
        .fromCallable((() -> JsonRestCaller.readJsonFromUrl(buildUrl())))
        .subscribeOn(Schedulers.io())
        .subscribeWith(new DisposableObserver<JsonObject>() {
            @Override
            public void onNext(JsonObject jsonObject) {
                try {
                    parseJson(jsonObject);
                } catch (IOException e) {
                    Log.e(TAG, e.getMessage());
                }
            }
            @Override
            public void onError(Throwable e) {
                Log.e(TAG, e.getMessage());
            }
            @Override
            public void onComplete() {
            }
    }));
}

Now all I want to do is wait for the parseJson() to complete so the method buildLocationFromDetails can work with the details retrieved in parseJson.

I read something about blocking operators but I am not sure how to make them work in my case. Also I found examples where someone just waited for a while to make sure a result was available but I would not know how long to wait for and that does not strike me as the right approach.


Solution

  • You can try something like below

    //Create a method which will parse json and return the result in String 
    //(I am assuming string as parse response for simplicity)
    public Observable<String> parseJson(JsonObject jsonObject) {
        return Observable
            .create(
                e -> {
                    //parse json code goes here.
                    // Once parsing done pass the details
                    e.onNext("Details from parsing json");
                    e.onComplete();
                }
            );
    }
    

    Now modify the above code which you have written,

    Observable
        .fromCallable((() -> JsonRestCaller.readJsonFromUrl(buildUrl())))
        //Pass the jsonObject from above to parseJson() method
        .flatMap(jsonObject -> parseJson(jsonObject))
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        //details is the string from parsing json
        .subscribe(
            details -> buildLocationFromDetails(details),
            error -> new Throwable(error)
        );
    

    Hope this helps.