在改造之后调用一个函数并且rxjava完成

时间:2015-11-20 15:14:05

标签: android retrofit rx-java

这是我的代码

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());

我应该怎么做,以便在通话完成时,在

  

返回apiInterface.getSuggestion()

  

返回Observable.just(null)

将调用两个不同的功能(每种情况一个)?当然,该函数需要处理从调用返回的数据。

顺便说一句,第二个flatMap返回此错误:

'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>)'

如果有帮助,这里是我的submitDataToAnalyze和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);

3 个答案:

答案 0 :(得分:3)

关于mapflatMap之间的区别 - 对于所有情况,确实没有简单的答案。总的来说,我这样做是这样的:

我使用map进行所有简单的一对一转换:链中的每个X都应转换为一个Y.

一些例子:

  • 通过大写
  • String转换为另一个String
  • 通过计算总和
  • Pair<Integer, Integer>转换为Integer
  • 通过查找最大值将List<Double>转换为Double 正如您所看到的,X和Y可以是任何类型(事实上,其中一个或两个可能是复杂的数据类型,如Collection) - 但是,对于每个输入实体,您仍然可以获得输出实体。

我使用flatMap表示至少满足下列条件之一的情况:

  • 转换本质上是异步的,例如网络请求
  • 转换不一定为每个输入产生一个输出,例如它可以为每个输入产生一个或多个输出
  • 转换有一些明显的错误或类似错误的条件,应该在那里解决而不是沿着链传播 - 我认为你的例子属于这种情况(以及作为异步网络调用)。

如果这三个条件听起来很熟悉,那是因为Erik Meijer在他的演讲中列出了这些条件:https://www.youtube.com/watch?v=sTSQlYX5DU0

关于更新代码中的编译错误 - 正确的类型声明应如下所示:

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);
        }
    }

由于getSuggestion返回的Observable<BasicResponse>必须是第一个Func1的返回类型 - 即使返回的实际值必须为null

我认为你的误解在于后面的内容,所以让我们来看看。然后RxJava没有通过链中的Observable<BasicResponse> - 因为您使用flatMap,它将在内部订阅您已创建的Observable<BasicResponse>,然后将该Observable发出的每个项目并传递 。这也是下一个Func1必须是Func1<BasicResponse, Observable<Integer>>而不是Func1<Observable<BasicResponse>, Observable<Integer>>的原因。在链中等待的任何函数的输入类型必须是BasicReponse,因为这是&#34; unpacked&#34;的类型。来自Observable<BasicResponse>的商品。我希望这很清楚,如果有点冗长。

要回到最后一部分的mapflatMap,您可以使用其中任何一个。如果您正确使用它,flatMap始终有效。但是map通常可以更短(并且可能更高效,因为它不会创建更多的内部Observable)。一般情况下,如果您有一个flatMap并且在每个分支中只返回Observable.just(),您也可以使用简单的地图。所以你可能会把你的代码重写为:

.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;
        }
    }

答案 1 :(得分:1)

flatMap应该返回一个可观察对象,因此return null应该是return Observable.just(null)而不是null。当您将其他运算符链接到flatmap时,直接返回$(document).on("click", selectorString, function(event) { // do stuff }); 将导致NPE。

之后,您可以链接下一个操作。使用什么操作符实际上取决于您希望该功能执行的操作。

答案 2 :(得分:1)

两个建议:

使用filter

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

或在Observable.empty()中返回flatMap

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