retrofix和rxjava完成之后调用函数 [英] Call a function after retrofix and rxjava completes
问题描述
下面是我的code
最后ApiInterface apiInterface = restAdapter.create(ApiInterface.class);
apiInterface.submitDataToAnalyze(dataToAnalyze,852741963,1,123,LALALA,2015年11月20日)
.flatMap(新FUNC1< BasicResponse,可观察到的与LT;>>(){
@覆盖
公众可观察<>致电(BasicResponse basicResponse){
如果(basicResponse.getResult()== 1){
返回apiInterface.getSuggestion(dataToAnalyze,852741963,1,123,LALALA,二○一五年十一月二十零日);
}其他{
返回null; //错误
}
}
})flatMap(新FUNC1<&可观察到的LT;>中整数GT;(){
@覆盖
公共整数通话(可观察到的与LT;>输入){
如果(输入== NULL){
//更新表
返回0;
}其他{
//更新使用数据检索apiInterface.getSuggestion另一个表
返回1;
}
}
})subscribeOn(Schedulers.io())observeOn(AndroidSchedulers.mainThread());
我应该怎么做,这样调用完成时,无论是在
返回apiInterface.getSuggestion()
块引用>或
返回Observable.just(空)
块引用>两个不同的功能(一个用于每种情况)将被称为?当然,该功能需要与来自调用返回的数据进行工作。
顺便说一下第二flatMap返回此错误:
'flatMap(rx.functions.Func1&LT ;?超强的java.lang.Object ,?延伸rx.Observable<>>)中的rx.Observable不能适用于'(匿名rx.functions.Func1< rx.Observable<>,&java.lang.Integer的GT;)
如果有帮助,这是我的submitDataToAnalyze和getSuggestion接口
@POST(/ request.php)
观察到与LT; BasicResponse> submitDataToAnalyze(@Query(行动)串动,@Query(AUTH)字符串AUTH,@Query(VER)诠释版本,@Query(的「uuid」)字符串UUID,@Query(dataToAnalyze)字符串dataToAnalyze,
@Query(requestForDate)字符串requestForDate);@POST(/ request.php)
观察到与LT; BasicResponse> getSuggestion(@Query(行动)串动,@Query(AUTH)字符串AUTH,@Query(VER)诠释版本,@Query(的「uuid」)字符串UUID,@Query(dataToAnalyze)字符串dataToAnalyze,
@Query(requestForDate)字符串requestForDate);
解决方案关于之间的差异
地图
和flatMap
- 有真正适用于所有情况没有简单的答案。总的来说,我接近它的是这样的:我用
地图
所有简单的一比一的转换:每次,归结链X应该转化为一个Y一些例子:
- 变换
字符串
另一个字符串
由上壳体它- 变换
对<整数,整数GT;
到整数
通过计算总和- 变换
列表与LT;双>
到双击
通过寻找最大
正如你所看到的X和Y可以是任何类型的(实际上是一方或双方可以像一个复杂的数据类型的收藏
) - 但尽管如此,对于每个输入实体您得到一个输出实体。我用
flatMap
的情况下以下的至少一个适用:
- 的转型是由它的性质是异步的,例如网络请求
- 改造不一定产生每个输入一个输出,例如它可以产生一个或多个输出每个输入
- 的转变有应该就在那里解决,而不是一些明显的错误或错误样的条件下向下传播链 - 我认为你的例子在这种情况下(以及作为一个异步网络调用)下降李。 >
如果这三个条件听起来很熟悉,那是因为埃里克·梅杰在他的演讲中列出他们在这里:的https: //www.youtube.com/watch?v=sTSQlYX5DU0
关于更新的code编译错误 - 正确的类型声明应该是这样的:
<$p$p><$c$c>apiInterface.submitDataToAnalyze(\"dataToAnalyze\",\"852741963\",1,\"123\",\"lalala\",\"2015-11-20\")
.flatMap(新FUNC1&LT; BasicResponse,可观察到的与LT; BasicResponse&GT;&GT;(){
@覆盖
公众可观察&LT; BasicResponse&GT;致电(BasicResponse basicResponse){
如果(basicResponse.getResult()== 1){
返回apiInterface.getSuggestion(dataToAnalyze,852741963,1,123,LALALA,二○一五年十一月二十零日);
}其他{
返回Observable.just(NULL);
}
}
})
.flatMap(新FUNC1&LT; BasicResponse,可观察到的与LT;整数GT;&GT;(){
@覆盖
公众可观察&LT;整数GT;调用(BasicResponse输入){
如果(输入== NULL){
//更新表
返回Observable.just(0);
}其他{
//更新使用数据检索apiInterface.getSuggestion另一个表
返回Observable.just(1);
}
}
由于
getSuggestion
返回观测与LT; BasicResponse&GT;
必须是第一个<$ C $的返回类型C> FUNC1 - 即使实际的返回值必须空
我觉得你误会在于在下面,让我们来看看。 RxJava不会那么没有通过
观测与LT; BasicResponse&GT;
环比下跌 - 因为你正在使用flatMap
将在内部认购在观测与LT; BasicResponse&GT;
您已经创建,然后将需要的通过观测所发射的每个项目的和通过的是下来。这也是为什么在未来FUNC1
必须是一个FUNC1&LT; BasicResponse,可观察到的与LT;整数GT;&GT;
- 而不是FUNC1&LT;&可观察到的LT; BasicResponse&gt;中可观察到的和LT;整数GT;&GT;
。输入类型等环比下滑任何函数都必须BasicReponse
,因为这是对解包的项目从类型观测&LT; BasicResponse&GT;
。我希望这是明确的,如果有点冗长。要回来
地图
与flatMap
的最后一部分 - 你可以使用其中之一。flatMap
总是工作,如果你正确地使用它。但地图
往往是短(可能有点更有效,因为它不会产生任何更多的内部观测量)。一般情况下,如果你有一个flatMap
,并在每个分支你只返回一个Observable.just()
你可以只如用一个简单的地图。所以,你很可能重写code为:.MAP(新FUNC1&LT; BasicResponse,整数GT;(){
@覆盖
公共整数调用(BasicResponse输入){
如果(输入== NULL){
//更新表
返回0;
}其他{
//更新使用数据检索apiInterface.getSuggestion另一个表
返回1;
}
}Here's my code
final ApiInterface apiInterface=restAdapter.create(ApiInterface.class); apiInterface.submitDataToAnalyze("dataToAnalyze","852741963",1,"123","lalala","2015-11-20") .flatMap(new Func1<BasicResponse, Observable<?>>() { @Override public Observable<?> call(BasicResponse basicResponse) { if (basicResponse.getResult() == 1){ return apiInterface.getSuggestion("dataToAnalyze","852741963",1,"123","lalala","2015-11-20"); }else{ return null; //error } } }).flatMap(new Func1<Observable<?>, Integer>() { @Override public Integer call(Observable<?> input) { if (input == null){ //update a table return 0; }else{ //update another table using data retrieved from apiInterface.getSuggestion return 1; } }
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
What should I do, so that when the call completes, either at
return apiInterface.getSuggestion()
or
return Observable.just(null)
Two different function (one for each case) would be called? And of course, the function need to work with the data returned from the call.
Btw the second flatMap returns this error:
'flatMap(rx.functions.Func1<? super java.lang.Object,? extends rx.Observable<?>>)' in 'rx.Observable' cannot be applied to '(anonymous rx.functions.Func1<rx.Observable<?>,java.lang.Integer>)'
If it helps, here's my interface for submitDataToAnalyze and getSuggestion
@POST("/request.php") Observable<BasicResponse> submitDataToAnalyze(@Query("action") String action, @Query("auth") String auth, @Query("ver") int ver, @Query("uuid") String uuid, @Query("dataToAnalyze") String dataToAnalyze, @Query("requestForDate") String requestForDate); @POST("/request.php") Observable<BasicResponse> getSuggestion(@Query("action") String action, @Query("auth") String auth, @Query("ver") int ver, @Query("uuid") String uuid, @Query("dataToAnalyze") String dataToAnalyze, @Query("requestForDate") String requestForDate);
解决方案Regarding the difference between
map
andflatMap
- 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(new Func1<BasicResponse, Observable<BasicResponse>>() { @Override public Observable<BasicResponse> call(BasicResponse basicResponse) { if (basicResponse.getResult() == 1){ return apiInterface.getSuggestion("dataToAnalyze","852741963",1,"123","lalala","2015-11-20"); } else { return Observable.just(null); } } }) .flatMap(new Func1<BasicResponse, Observable<Integer>>() { @Override public Observable<Integer> call(BasicResponse input) { if (input == null){ //update a table return Observable.just(0); } else { //update another table using data retrieved from apiInterface.getSuggestion return Observable.just(1); } }
Since
getSuggestion
returns anObservable<BasicResponse>
that must be the return type of the firstFunc1
- even if the actual value returned must benull
.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 usingflatMap
it will then internally subscribe to theObservable<BasicResponse>
that you've created and will then take each item emitted by that Observable and pass that down. That is also why the nextFunc1
must be aFunc1<BasicResponse, Observable<Integer>>
- and not aFunc1<Observable<BasicResponse>, Observable<Integer>>
. The input type of any function waiting down the chain must beBasicReponse
because that is the type of the "unpacked" items from yourObservable<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. Butmap
can often be shorter (and probably a bit more efficient, since it does not create any more internal Observables). In general, if you have aflatMap
and in each branch you just return anObservable.just()
you could just as well use a simple map. So you could probably rewrite your code as:.map(new Func1<BasicResponse, Integer>() { @Override public Integer call(BasicResponse input) { if (input == null){ //update a table return 0; } else { //update another table using data retrieved from apiInterface.getSuggestion return 1; } }
这篇关于retrofix和rxjava完成之后调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!