在RxJava中,链接观察对象时如何传递变量?

在RxJava中,链接观察对象时如何传递变量?,java,rx-java,reactive-programming,flatmap,Java,Rx Java,Reactive Programming,Flatmap,我正在使用RxJava链接异步操作,我想向下游传递一些变量: Observable .from(modifications) .flatmap( (data1) -> { return op1(data1); }) ... .flatmap( (data2) -> { // How to access data1 here ? return op2(data2); }) 这似乎是一种常见的模式,但我找不到有关它的信息。一种

我正在使用RxJava链接异步操作,我想向下游传递一些变量:

Observable
   .from(modifications)
   .flatmap( (data1) -> { return op1(data1); })
   ...
   .flatmap( (data2) -> { 
       // How to access data1 here ?
       return op2(data2);
   })

这似乎是一种常见的模式,但我找不到有关它的信息。

一种可能是使用函数调用:

private static Observable<T> myFunc(final Object data1) {
    return op1(data1)
        ...
        .flatmap( (data2) -> { 
            // I can access data1 here
            return op2(data2);
        });
}

Observable
   .from(modifications)
   .flatmap( (data1) -> { return myFunc(data1); })
私有静态可观察myFunc(最终对象数据1){
返回op1(数据1)
...
.flatmap((数据2)->{
//我可以在这里访问data1
返回op2(data2);
});
}
可观察
.来自(修改)
.flatmap((数据1)->{return myFunc(数据1);})

但是:如果我错了,请纠正我的错误,但这不像是一种反应式编程方式,另一种可能是将
op1
的结果映射到包含变量的
org.apache.commons.lang3.tuple.Pair
,并传递该变量:

Observable
   .from(modifications)
   .flatmap( (data1) -> {
       return op1(data1).map( obj -> { return Pair.of(data1,obj); });
   })
   ...
   .flatmap( (dataPair) -> { 
       // data1 is dataPair.getLeft()
       return op2(dataPair.getRight());
   })
这是可行的,但将变量隐藏在Pair/Triple/中会让人感觉有点不舒服。。。如果使用Java6表示法,它会变得非常冗长


我想知道是否有更好的解决方案,也许一些RxJava运营商可以提供帮助?

我从Couchbase论坛得到的建议是使用嵌套的可观察对象:

Observable
   .from(modifications)
   .flatmap( (data1) -> { 
       return op1(data1)
           ...
           .flatmap( (data2) -> { 
               // I can access data1 here
               return op2(data2);
           })
   });

编辑:我会将此标记为已接受的答案,因为它似乎是最推荐的答案。如果您的处理太复杂,无法嵌套所有内容,您也可以通过函数调用检查解决方案。

此线程上的解决方案可以工作,但对于复杂的链,它会使代码难以读取,我必须传递多个值,我所做的是创建一个包含所有参数的私有类,我发现这样代码更可读

private class CommonData{
   private string data1;
   private string data2;

   *getters and setters*
}
...
final CommonData data = new CommonData();
Observable
   .from(modifications)
   .flatmap( (data1) -> { 
       data.setData1(data1);
       return op1(data1); 
   })
   ...
   .flatmap( (data2) -> { 
       data2 = data.getData1() + "data 2... ";
       data.setData2(data2);
       return op2(data2);
   })

希望有帮助

flatmap可以使用第二个参数:

Observable.just("foo")
                .flatMap(foo -> Observable.range(1, 5), Pair::of)
                .subscribe(pair -> System.out.println("Result: " + pair.getFirst() + " Foo: " + pair.getSecond()));
来源:

您可以使用“全局”变量来实现以下目标:

 Object[] data1Wrapper = new Object[]{null};
 Object[] data2Wrapper = new Object[]{null};
 Observable
    .from(modifications)
    .flatmap(data1 -> {
        data1Wrapper[0] = data1;
        return op1(data1)
     })
      ...
    .flatmap(data2 -> { 
        // I can access data1 here use data1Wrapper[0]
        Object data1 = data1Wrapper[0];
        data2Wrapper[0] = data2;
        return op2(data2);
     })

我知道这是一个老问题,但是使用RxJava2和lambda, 您可以使用以下内容:

Observable
.from(modifications)
.flatMap((Function<Data1, ObservableSource<Data2>>) data1 -> {
                        //Get data 2 obeservable

                            return Observable.just(new Data2())
                        }
                    }, Pair::of)
可观察
.来自(修改)
.flatMap((函数)数据1->{
//获取可维护的数据2
返回Observable.just(新数据2())
}
},成对的)

在下一个流(flatmap/map)中,您的输出对将是(data1,data2)

实际上我们有一个库,它简化了调用链

添加为渐变依赖项:

implementation 'io.reactivex.rxjava2:rxjava:2.2.1'
implementation 'com.github.pakoito.Komprehensions:komprehensions-rx2:1.3.2'
用法(Kotlin):


这是我发现自己经常做的事情,到目前为止效果很好。嗯,这与我的“在流之外存储数据”没有太大区别。我不认为这样做有什么错,但每当我觉得我需要接触结对类时,我也觉得我做错了什么。我使用它的次数,然后在我对我的领域有了更好的了解后重新计算。这就是我想到的解决方案,尽管它会创建大量垃圾制造
成对
实例,只是为了将
数据1
放在
obj
旁边。我想知道一个
组合
是否有效。这与您的第一个选项有很大不同吗?@是的,我想它的功能类似于使用嵌套调用。对于复杂的处理,这可能毕竟不是一个坏的选择。不幸的是,这可能不是线程安全的(取决于您的代码RxJava将在多个线程上运行计算)。我很困惑,如果RxJava为数据创建多个线程,为什么私有的非静态变量会是线程“不安全的”,CommonData实例将在线程之间共享,即使它不是静态的。(这应该可以通过一些显示当前线程和CommonData值的日志进行测试)我需要找到另一个解决方案,因为如果必须执行以下操作:if(boolean)return observer 1 else return observer 2;您必须在这两个平面上绘制平面图,这将是。。badhow to import Pair?@DynoCris您可以编写自己的或从一些libs(仅谷歌java+Pair)简单而干净地导入它。这应该是可以接受的答案。这是错误的建议,不要将数据存储在流之外,使用SwitchMap或类似的方法传递数据。这是反模式。
val observable = doFlatMap(
    { Observable.from(modifications) },
    { data1 -> op1(data1) },
    { data1, data2 -> op2(data2) },
    { data1, data2, data3 -> op3(data1, data2, data3) }
)