在 RxJava 中,如何在链接可观察对象时传递变量?
In RxJava, how to pass a variable along when chaining observables?
我正在使用 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); })
但是:如果我错了请纠正我,但感觉不像是响应式编程的方式
另一种可能性是将 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 操作员可以提供帮助?
我从 Couchbase 论坛得到的建议是使用嵌套的 observables:
Observable
.from(modifications)
.flatmap( (data1) -> {
return op1(data1)
...
.flatmap( (data2) -> {
// I can access data1 here
return op2(data2);
})
});
编辑:我将其标记为已接受的答案,因为它似乎是最受推荐的。如果您的处理太复杂而无法嵌套所有内容,您还可以通过函数调用检查解决方案。
这个线程的解决方案有效,但对于复杂的链,它使代码难以阅读,我不得不传递多个值,我所做的是创建一个包含所有参数的私有 class,我发现代码是这样更具可读性,
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);
})
希望对您有所帮助
平面图可以带第二个参数:
Observable.just("foo")
.flatMap(foo -> Observable.range(1, 5), Pair::of)
.subscribe(pair -> System.out.println("Result: " + pair.getFirst() + " Foo: " + pair.getSecond()));
您可以使用 "global" 变量来实现:
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/map) 中,您的输出对将是 (data1, data2)
实际上我们有库,可以简化调用链。
https://github.com/pakoito/Komprehensions
添加为 Gradle 依赖项:
implementation 'io.reactivex.rxjava2:rxjava:2.2.1'
implementation 'com.github.pakoito.Komprehensions:komprehensions-rx2:1.3.2'
用法(Kotlin):
val observable = doFlatMap(
{ Observable.from(modifications) },
{ data1 -> op1(data1) },
{ data1, data2 -> op2(data2) },
{ data1, data2, data3 -> op3(data1, data2, data3) }
)
我正在使用 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); })
但是:如果我错了请纠正我,但感觉不像是响应式编程的方式
另一种可能性是将 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 操作员可以提供帮助?
我从 Couchbase 论坛得到的建议是使用嵌套的 observables:
Observable
.from(modifications)
.flatmap( (data1) -> {
return op1(data1)
...
.flatmap( (data2) -> {
// I can access data1 here
return op2(data2);
})
});
编辑:我将其标记为已接受的答案,因为它似乎是最受推荐的。如果您的处理太复杂而无法嵌套所有内容,您还可以通过函数调用检查解决方案。
这个线程的解决方案有效,但对于复杂的链,它使代码难以阅读,我不得不传递多个值,我所做的是创建一个包含所有参数的私有 class,我发现代码是这样更具可读性,
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);
})
希望对您有所帮助
平面图可以带第二个参数:
Observable.just("foo")
.flatMap(foo -> Observable.range(1, 5), Pair::of)
.subscribe(pair -> System.out.println("Result: " + pair.getFirst() + " Foo: " + pair.getSecond()));
您可以使用 "global" 变量来实现:
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/map) 中,您的输出对将是 (data1, data2)
实际上我们有库,可以简化调用链。
https://github.com/pakoito/Komprehensions
添加为 Gradle 依赖项:
implementation 'io.reactivex.rxjava2:rxjava:2.2.1'
implementation 'com.github.pakoito.Komprehensions:komprehensions-rx2:1.3.2'
用法(Kotlin):
val observable = doFlatMap(
{ Observable.from(modifications) },
{ data1 -> op1(data1) },
{ data1, data2 -> op2(data2) },
{ data1, data2, data3 -> op3(data1, data2, data3) }
)