retrofix和rxjava完成之后调用函数 [英] Call a function after retrofix and rxjava completes

查看:1133
本文介绍了retrofix和rxjava完成之后调用函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的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 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(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 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(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆