我想链接两个RxJava Single
实例来创建一个Observable
,它会发出两个结果。另外,我需要第一个Single
的结果来创建第二个。public static <A extends C, B extends C, C> Observable<C> chain(final Single<A> a, final Function<A, Single<B>> f) {
return Observable.concat(
a.toObservable(),
a.flatMap(f::apply).toObservable());
}
。
以下是我的尝试:
final Observable<Event> task = MoreObservables.chain(
writeFile("Hello, world", "hello.txt"),
writeFileEvent -> processFile(writeFileEvent.path));
用法可能如下所示:
Error:(54, 61) java: incompatible types: cannot infer type-variable(s) A,B,C
(argument mismatch; bad return type in lambda expression
io.reactivex.Single<ProcessFileEvent> cannot be converted to io.reactivex.Single<Event>)
然而,Java抱怨它无法解析类型:
ProcessFileEvent
当然,Event
实现public final Optional<P_OUT> max(Comparator<? super P_OUT> comparator) {
return reduce(BinaryOperator.maxBy(comparator));
}
。
如何编写我的函数以便Java可以找出类型?或者有更简单的方法来实现这个?
答案 0 :(得分:2)
如果不知道确切的writeFile
和processFile
签名(来自简单模拟,它应该编译),很难说出为什么会出现编译错误。
无论如何,更惯用的方法是使用compose()
方法和自定义ObservableTransformer
,以便拥有一个链而不是包装方法,使链变得不那么可读(read this) 。
这里也存在逻辑问题,因为您正在使用concat()
并使用两次Observable
,您实际上将执行两次操作(将被订阅两次),这可能导致最糟糕情况下的性能问题,或者是一个主要的微妙错误。 (在您的示例中,您将两次写入同一文件)
我认为你应该在这种情况下使用publish,为了执行一次,与merge一起执行,这将导致Observable将发出A的结果,然后执行B结果为A,并将发出此结果:
变压器:
class PublishAndMergeTransformer<A extends C, B extends C, C> implements ObservableTransformer<A, C> {
final Function<A, Single<B>> f;
public PublishAndMergeTransformer(Function<A, Single<B>> f) {
this.f = f;
}
@Override
public ObservableSource<C> apply(Observable<A> a) {
return a.publish(aObservable ->
Observable.merge(
aObservable,
aObservable
.flatMap(a1 -> f.apply(a1).toObservable())
)
);
}
}
和使用示例:
writeFile("Hello, world", "hello.txt")
.toObservable()
.compose(new PublishAndMergeTransformer<>(writeFileEvent -> processFile(writeFileEvent.path)));