Call A Function After Retrofit And Rxjava Completes
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 anotherString
by upper casing it - transform a
Pair<Integer, Integer>
to anInteger
by calculating the sum - transform a
List<Double>
to aDouble
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 aCollection
) - 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"