Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RxJava:如何表达doOnFirst()?_Java_Rx Java_Reactive Programming_Rx Java2_Rx Android - Fatal编程技术网

RxJava:如何表达doOnFirst()?

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 | |

我使用的是RxJava,我有一个
可观察的
,里面有多个项目。我想做的是在第一个项目上运行函数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);
                }
            });
        });
    }
}