在改造和 rxjava 完成后调用一个函数 [英] Call a function after retrofit and rxjava completes

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

问题描述

这是我的代码

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

返回 apiInterface.getSuggestion()

return apiInterface.getSuggestion()

返回 Observable.just(null)

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.

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

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

如果有帮助,这是我的 submitDataToAnalyze 和 getSuggestion 界面

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

推荐答案

关于 mapflatMap 之间的区别 - 实际上没有适用于所有情况的简单答案.一般来说,我是这样处理的:

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:

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

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

一些例子:

  • 通过大写将一个 String 转换为另一个 String
  • 通过计算总和将 Pair 转换为 Integer
  • 通过查找最大值将 List 转换为 Double正如您所看到的,X 和 Y 可以是任何类型(实际上,其中一个或两个都可以是复杂的数据类型,例如 Collection)——但是,对于每个输入实体,您都会得到一个输出实体.
  • 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.

我将 flatMap 用于以下至少一项适用的情况:

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

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

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

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

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

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.

我认为您的误解在于以下内容,所以让我们来看看.然后,RxJava 不会将 Observable 向下传递 - 因为您使用的是 flatMap,它将在内部订阅 Observable> 你已经创建了,然后将该 Observable 发出的每个项目 并传递那个.这也是为什么下一个 Func1 必须是 Func1> - 而不是 Func1, Observable<;整数>>.任何在链中等待的函数的输入类型必须是 BasicReponse,因为这是来自 Observable 的解包"项的类型.我希望这很清楚,虽然有点冗长.

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.

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

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

这篇关于在改造和 rxjava 完成后调用一个函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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