[英]RxJava Observable get notified on first emission
I have three Observables which I combine with combineLastest: 我将三个Observable与CombineLastest结合使用:
Observable<String> o1 = Observable.just("1");
Observable<String> o2 = Observable.just("2");
Observable<String> o3 = Observable.just("3");
Observable.combineLatest(o1, o2, o3, new Func3<String, String, String, Object>() {
@Override
public Object call(String s, String s2, String s3) {
return null;
}
});
I want to be notified about the first emission of one of the Observables without ignoring the later emissions, which I guess first operator would do. 我想被通知有关一个可观察物的第一次排放,而又不忽略后来的排放,我想第一位操作员会这样做。 Is there a convenient operator for that like (example): 是否有类似这样的便捷运算符(示例):
o1.doOnFirst(new Func1<String, Void>() {
@Override
public Void call(String s) {
return null;
}
})
I think you can have a practical doOnFirst
with a simple take
if you're handling a stream: 我认为,如果您要处理流,则可以通过简单的操作take
实现实用的doOnFirst
:
public static <T> Observable<T> withDoOnFirst(Observable<T> source, Action1<T> action) {
return source.take(1).doOnNext(action).concatWith(source);
}
This way the action is only bound to the first item. 这样,动作仅绑定到第一项。
This could be changed to handle observables which are not backed by streams adding skip
to skip the already taken items: 可以将其更改为处理没有流支持的可观察对象,添加skip
以跳过已采取的项目:
public static <T> Observable<T> withDoOnFirstNonStream(Observable<T> source, Action1<T> action) {
return source.take(1).doOnNext(action).concatWith(source.skip(1));
}
There are a couple of solutions I can think of. 我可以想到几种解决方案。 The first one is an ugly but simple hack of doOnNext. 第一个是doOnNext的丑陋但简单的技巧。 Just add a boolean field to the Action1
indicating whether the first item has been received. 只需向Action1
添加一个布尔字段,指示是否已接收到第一项。 Once received, do whatever it is you want to do, and flip the boolean. 收到后,执行您想做的任何事情,然后翻转布尔值。 For example: 例如:
Observable.just("1").doOnNext(new Action1<String>() {
boolean first = true;
@Override
public void call(String t) {
if (first) {
// Do soemthing
first = false;
}
}
});
The second one is to subscribe twice on the observable you want to monitor using publish
or share()
, with one of those publications going through first
(depending on whether you want to manually connect to the published observable). 第二个是使用publish
或share()
对要监视的可观察对象进行两次订阅,其中一个发布会first
(取决于您是否要手动连接到已发布的可观察对象)。 You'll end up with two separate observables that emit the same items, only the first one will stop after the first emission: 您最终将得到两个单独的可观察项,它们发出相同的项,只有第一个可观察项将在第一次发出后停止:
ConnectableObservable<String> o1 = Observable.just("1").publish();
o1.first().subscribe(System.out::println); //Subscirbed only to the first item
o1.subscribe(System.out::println); //Subscirbed to all items
o1.connect(); //Connect both subscribers
Using rxjava-extras : 使用rxjava-extras :
observable
.compose(Transformers.doOnFirst(System.out::println))
It's unit tested and under the covers just uses a per-subscription counter in an operator. 它已经过单元测试,在幕后仅在运营商中使用每个订阅计数器。 Note that per-subscription is important as there are plenty of uses cases where an observable instance gets used more than once and we want the doOnFirst
operator to apply each time. 请注意,按预订非常重要,因为在许多用例中,可观察实例被多次使用,并且我们希望doOnFirst
运算符每次都适用。
For convenience, I created these extension functions for Flowable
and Observable
. 为了方便起见,我为Flowable
和Observable
创建了这些扩展功能。
Note, that with doOnFirst()
the action will be called before the first element emission, whilst doAfterFirst()
will firstly emit the first item and then perform the action. 注意,使用doOnFirst()
会在发出第一个元素之前调用该动作,而doAfterFirst()
会首先发出第一个元素然后执行该动作。
fun <T> Observable<T>.doOnFirst(onFirstAction: (T) -> Unit): Observable<T> =
take(1)
.doOnNext { onFirstAction.invoke(it) }
.concatWith(skip(1))
fun <T> Flowable<T>.doOnFirst(onFirstAction: (T) -> Unit): Flowable<T> =
take(1)
.doOnNext { onFirstAction.invoke(it) }
.concatWith(skip(1))
fun <T> Observable<T>.doAfterFirst(afterFirstAction: (T) -> Unit): Observable<T> =
take(1)
.doAfterNext { afterFirstAction.invoke(it) }
.concatWith(skip(1))
fun <T> Flowable<T>.doAfterFirst(afterFirstAction: (T) -> Unit): Flowable<T> =
take(1)
.doAfterNext { afterFirstAction.invoke(it) }
.concatWith(skip(1))
Usage is as simple as this: 用法很简单:
Flowable.fromArray(1, 2, 3)
.doOnFirst { System.err.println("First $it") }
.subscribe { println(it) }
Output: 输出:
// First 1
// 1
// 2
// 3
And: 和:
Flowable.fromArray(1, 2, 3)
.doAfterFirst { System.err.println("First $it") }
.subscribe { println(it) }
Output: 输出:
// 1
// First 1
// 2
// 3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.