我正在使用RxJava链接异步操作,我想在下游传递一些变量:
Observable
.from(modifications)
.flatmap( (data1) -> { return op1(data1); })
...
.flatmap( (data2) -> {
// How to access data1 here ?
return op2(data2);
})
这似乎是一种常见模式,但我无法找到有关它的信息。
答案 0 :(得分:52)
我从Couchbase论坛获得的建议是使用嵌套的observable:
Observable
.from(modifications)
.flatmap( (data1) -> {
return op1(data1)
...
.flatmap( (data2) -> {
// I can access data1 here
return op2(data2);
})
});
编辑:我会将此标记为已接受的答案,因为它似乎是最推荐的答案。如果您的处理过于复杂而无法嵌套所有内容,您还可以通过函数调用来检查解决方案。
答案 1 :(得分:12)
另一种可能性是将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 /中感觉有点不舒服......如果使用Java 6表示法,它会变得非常冗长。
我想知道是否有更好的解决方案,也许一些RxJava运营商可以提供帮助?
答案 2 :(得分:5)
一种可能性是使用函数调用:
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); })
但是:如果我错了,请纠正我,但感觉不像反应式编程方式
答案 3 :(得分:4)
flatmap可以采取第二个arg:
Observable.just("foo")
.flatMap(foo -> Observable.range(1, 5), Pair::of)
.subscribe(pair -> System.out.println("Result: " + pair.getFirst() + " Foo: " + pair.getSecond()));
答案 4 :(得分:1)
此线程上的解决方案有效,但对于复杂的链,它使代码难以阅读,我必须传递多个值,我所做的是创建一个包含所有参数的私有类,我发现代码更具可读性,< / p>
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);
})
希望有所帮助
答案 5 :(得分:1)
您可以使用“全局”变量来实现:
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);
})
答案 6 :(得分:0)
我知道这是一个老问题,但是使用RxJava2和lambda, 您可以使用类似的内容:
Observable
.from(modifications)
.flatMap((Function<Data1, ObservableSource<Data2>>) data1 -> {
//Get data 2 obeservable
return Observable.just(new Data2())
}
}, Pair::of)
在下一个流程(平面图/地图)上,您的输出对将为(data1,data2)
答案 7 :(得分:0)
实际上,我们有一个可以简化调用链的库。
https://github.com/pakoito/Komprehensions
添加为Gradle依赖项:
implementation 'io.reactivex.rxjava2:rxjava:2.2.1'
implementation 'com.github.pakoito.Komprehensions:komprehensions-rx2:1.3.2'
用法(科特琳):
val observable = doFlatMap(
{ Observable.from(modifications) },
{ data1 -> op1(data1) },
{ data1, data2 -> op2(data2) },
{ data1, data2, data3 -> op3(data1, data2, data3) }
)