Skip to content Skip to sidebar Skip to footer

Call A Function After Retrofit And Rxjava Completes

Here's my code final ApiInterface apiInterface=restAdapter.create(ApiInterface.class); apiInterface.submitDataToAnalyze('dataToAnalyze','852741963',1,'123','lalala','2015-11-20')

Solution 1:

Regarding the difference between map and flatMap - there's really no easy answer that applies to all situations. In general I approach it the like this:

I use map for all easy one-to-one transformations: Every X that comes down the chain should be transformed to one Y.

Some examples:

  • transform a String to another String by upper casing it
  • transform a Pair<Integer, Integer> to an Integer by calculating the sum
  • transform a List<Double> to a Double by finding the maximum As you can see X and Y can be of any types (and indeed one or both could be a complex data type like a Collection) - but still, for each input entity you get an output entity.

I use flatMap for situations where at least one of the following applies:

  • the transformation is by its nature asynchronous, for example a network request
  • the transformation does not necessarily yield one output for each input, for example it could produce one or more outputs for each input
  • the transformation has some obvious error or error-like conditions that should be addressed right there and not be propagated down the chain - I think your example falls under that case (as well as being an async network call).

If these three conditions sound familiar, that's because Erik Meijer listed them in his talk here: https://www.youtube.com/watch?v=sTSQlYX5DU0

Regarding the compile error in your updated code - the correct type declarations should look like this:

apiInterface.submitDataToAnalyze("dataToAnalyze","852741963",1,"123","lalala","2015-11-20")
.flatMap(newFunc1<BasicResponse, Observable<BasicResponse>>() {
    @OverridepublicObservable<BasicResponse> call(BasicResponse basicResponse) {
        if (basicResponse.getResult() == 1){
            return apiInterface.getSuggestion("dataToAnalyze","852741963",1,"123","lalala","2015-11-20");
        } else {
            returnObservable.just(null);
        }
    }
})
.flatMap(newFunc1<BasicResponse, Observable<Integer>>() {
    @OverridepublicObservable<Integer> call(BasicResponse input) {
        if (input == null){
            //update a tablereturnObservable.just(0);
        } else {
            //update another table using data retrieved from apiInterface.getSuggestionreturnObservable.just(1);
        }
    }

Since getSuggestion returns an Observable<BasicResponse> that must be the return type of the first Func1 - even if the actual value returned must be null.

I think your misunderstanding lies at what follows, so let's have a look. RxJava does then not pass the Observable<BasicResponse> down the chain - since you are using flatMap it will then internally subscribe to the Observable<BasicResponse> that you've created and will then take each item emitted by that Observable and pass that down. That is also why the next Func1 must be a Func1<BasicResponse, Observable<Integer>> - and not a Func1<Observable<BasicResponse>, Observable<Integer>>. The input type of any function waiting down the chain must be BasicReponse because that is the type of the "unpacked" items from your Observable<BasicResponse>. I hope this was clear, if a bit verbose.

To come back to map vs. flatMap for the final part - you can use either one. flatMap always works, if you are using it correctly. But map can often be shorter (and probably a bit more efficient, since it does not create any more internal Observables). In general, if you have a flatMap and in each branch you just return an Observable.just() you could just as well use a simple map. So you could probably rewrite your code as:

.map(newFunc1<BasicResponse, Integer>() {
    @OverridepublicIntegercall(BasicResponse input) {
        if (input == null){
            //update a tablereturn0;
        } else {
            //update another table using data retrieved from apiInterface.getSuggestionreturn1;
        }
    }

Solution 2:

The flatMap should return an observable, so instead of return null it should be return Observable.just(null). Returning null directly will result in a NPE when you chain other operators to the flatmap.

After that you can chain the next operation. What operator to use really depends on what you want that function to do.

Solution 3:

Two suggestions:

Use filter:

apiInterface.submitDataToAnalyze(...)
  .filter(br -> br.getResult() ==1)
  .flatMap(new Func1<BasicResponse, Observable<?>>() {
    @OverridepublicObservable<?> call(BasicResponse basicResponse) {
       return apiInterface.getSuggestion(...);
    }
  })
...

or return Observable.empty() in the flatMap:

if (basicResponse.getResult() == 1){
    return apiInterface.getSuggestion(...);
}else{
    return Observable.empty();
}

Post a Comment for "Call A Function After Retrofit And Rxjava Completes"