RxJava:如何表达doOnFirst()?
我使用的是RxJava,我有一个RxJava:如何表达doOnFirst()?,java,rx-java,reactive-programming,rx-java2,rx-android,Java,Rx Java,Reactive Programming,Rx Java2,Rx Android,我使用的是RxJava,我有一个可观察的,里面有多个项目。我想做的是在第一个项目上运行函数A,在所有项目上运行函数B,并在可观察的完成时运行函数C: -----1-----2-----3-----|--> | | | | run A | | | | | | | run B run B run B | |
可观察的,里面有多个项目。我想做的是在第一个项目上运行函数A,在所有项目上运行函数B,并在可观察的
完成时运行函数C:
-----1-----2-----3-----|-->
| | | |
run A | | |
| | | |
run B run B run B |
|
run C
有没有一种巧妙的方法可以用lambda函数来表达这一点?我已经有了以下解决方案,但它看起来很难看,我怀疑有更好的方法可以做到这一点:
observable.subscribe(
新行动1(){
布尔值优先=真;
@凌驾
公共作废通知(项目){
如果(第一){
runA(项目);
第一个=假;
}
runB(传真1);
}
},
可丢弃->{},
()->runC());
已经内置了doOnNext
和doOnTerminate
(或类似)功能,因此听起来好像只缺少对第一项执行操作。这里有一条路。您可以发布您的流,然后在一个块中流正常进行,而在单独的订阅中,我们只侦听第一个事件(使用first
),并在收到它时执行操作。下面是一个例子:
observable.publish(new Func1<Observable<Item>, Observable<Item>>() {
@Override
public Observable<Item> call(Observable<Item> itemObservable) {
itemObservable.first().subscribe((Item item) -> runA(item));
return itemObservable;
}
}).subscribe(/* some actions and subscription as usual ... */);
显然,使用Lambda语法,这一切看起来都好得多,以上是我的猜测。使用可观察。延迟封装每个订阅状态(作为一个布尔值,指示我们是否在第一条记录上)
下面是演示使用的可运行类:
import rx.Observable;
import rx.Observable.Transformer;
import rx.functions.Action1;
public class DoOnFirstMain {
public static void main(String[] args) {
Observable<Integer> o =
Observable.just(1, 2, 3)
.compose(doOnFirst(System.out::println);
// will print 1
o.subscribe();
// will print 1
o.subscribe();
}
public static <T> Transformer<T, T> doOnFirst(Action1<? super T> action) {
return o -> Observable.defer(() -> {
final AtomicBoolean first = new AtomicBoolean(true);
return o.doOnNext(t -> {
if (first.compareAndSet(true, false)) {
action.call(t);
}
});
});
}
}
导入接收。可观察;
进口rx.Observable.Transformer;
导入rx.functions.Action1;
公共类DoOnFirstMain{
公共静态void main(字符串[]args){
可观测o=
可观察。仅(1,2,3)
.compose(doOnFirst(System.out::println);
//将打印1
o、 订阅();
//将打印1
o、 订阅();
}
公共静态变压器doOnFirst(操作1我想我自己已经找到了一个简单的解决方案:
Observable-Observable=Observable.just(1,2,3).share();
可观察的.take(1).subscribe(this::runA);
可观察的(
这个::runB,
可丢弃->{},
这是(runC);
这是单线程的,它似乎也工作多线程,但我不得不承认我对这一点目前还不太自信。
使用发布是一个非常重量级的解决方案。我会尝试并提出一些更简单的。“DaveMoten,你介意解释一下为什么你认为它太重吗?你是指处理开销吗?”那publish
增加了语法方面的功能?在处理开销方面。如果我的解决方案是以操作符的形式编写的,以节省每次发射时的不稳定读取量,那么效率可能会更高。如果您的原始observable没有订阅的副作用,这将很好。@TBieniek这正是我实现它的方式。另外这篇文章的答案似乎过于复杂。你能保证runA
会在runB
之前为1
运行吗
在第一个示例的处理程序中,应该保证runA
首先发生。@tir38我不介意添加RxJava2示例,但RxJava2中的等效Observable是可流动的。是否要修改?
observable
.compose(Transformers.doOnFirst((Item item) -> runA(item)))
.subscribe(/* chain and subscribe as usual... */);
import rx.Observable;
import rx.Observable.Transformer;
import rx.functions.Action1;
public class DoOnFirstMain {
public static void main(String[] args) {
Observable<Integer> o =
Observable.just(1, 2, 3)
.compose(doOnFirst(System.out::println);
// will print 1
o.subscribe();
// will print 1
o.subscribe();
}
public static <T> Transformer<T, T> doOnFirst(Action1<? super T> action) {
return o -> Observable.defer(() -> {
final AtomicBoolean first = new AtomicBoolean(true);
return o.doOnNext(t -> {
if (first.compareAndSet(true, false)) {
action.call(t);
}
});
});
}
}
import java.util.concurrent.atomic.AtomicBoolean;
import io.reactivex.Flowable;
import io.reactivex.FlowableTransformer;
import io.reactivex.functions.Consumer;
public class DoOnFirstMain {
public static void main(String[] args) {
Flowable<Integer> f =
Flowable.just(1, 2, 3)
.compose(doOnFirst(System.out::println);
// will print 1
f.subscribe();
// will print 1
f.subscribe();
}
public static <T> FlowableTransformer<T, T> doOnFirst(Consumer<? super T> consumer) {
return f -> Flowable.defer(() -> {
final AtomicBoolean first = new AtomicBoolean(true);
return f.doOnNext(t -> {
if (first.compareAndSet(true, false)) {
consumer.accept(t);
}
});
});
}
}