我正在尝试使用Observable实现一个发出更改的类。 当对此observable进行订阅时,我想发送一个启动/初始化事件。然后我想发送通常的事件。
例如。假设我有两个不同的订户A和B.A和B在不同的时间开始订阅。如果MyClass.getChanges()发出事件号。 1,2,3,4和5。
如果A在事件1,2之间开始订阅,那么它应该收到以下事件: InitialEvent,2,3,4,5。
如果B在事件4和5之间开始订阅,那么B应该收到以下事件: InitialEvent,5。
如何使用RxJava执行此操作?
谢谢!
修改1
我想我需要解释一下每次发出时“InitialEvent”都不同。每次新订户开始从getChanged()订阅时,它都是由MyClass计算的。
我的场景是MyClass包含一个列表。 “initialEvent”包含订阅完成时的列表。然后,每个对此列表的更改都从getChanges()发出。
答案 0 :(得分:0)
您正在寻找的是PublishSubject
。主题热Observables
,因为在开始发布项目之前,他们不会等待Observers
到subscribe
。以下是关于Subjects的一些信息。
以下是您的用例
的快速演示 PublishSubject<String> subject = PublishSubject.create();
Observable<String> InitEvent = Observable.just("init");
Observable<String> A = subject.asObservable();
Observable<String> B = subject.asObservable();
subject.onNext("1");
A.startWith(InitEvent)
.subscribe(s -> System.out.println("A: " + s));
subject.onNext("2");
subject.onNext("3");
subject.onNext("4");
B.startWith(InitEvent)
.subscribe(s -> System.out.println("B: " + s));
subject.onNext("5");
答案 1 :(得分:0)
可能不是很优雅的方式如何使用旗帜?看起来你只想替换第一个发出的事件。
e.g。对于一个订阅,以下逻辑:
boolean firstTimeA = true;
myCustomObservable.subscribe(s -> {
System.out.println(firstTimeA ? "initEvent" : s.toString());
if(firstTimeA) firstTimeA = false;
});
由于您想要第二次订阅,只需创建一个firstTimeB
并将其更新为您的B订阅。
答案 2 :(得分:0)
如果我理解你的问题,那么这样的事情对你有用
int last = 0;
Observable obs;
List<Integer> list = new ArrayList<>();
public SimpleListObservable() {
obs = Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
while(last < 30) {
last++;
list.add(last);
subscriber.onNext(last);
}
subscriber.onCompleted();
}
});
}
public Observable<Integer> process() {
return Observable.from(list).concatWith(obs);
}
当source observable收集值时,它们会被添加到List
(您可以根据需要转换项目,过滤掉它们等),然后当ObserverB
订阅时,它将获得重播在继续源可观察输出之前已经在List
中收集的项目。
这个简单的测试应该证明结果
public void testSequenceNext() {
final SimpleListObservable obs = new SimpleListObservable();
final Observer<Integer> ob2 = Mockito.mock(Observer.class);
obs.process().subscribe(new Observer<Integer>() {
@Override
public void onCompleted() {
ob1Complete = true;
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onNext(Integer integer) {
System.out.println("ob1: " + integer);
if (integer == 20) {
obs.process().subscribe(ob2);
}
}
});
ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
Mockito.verify(ob2, Mockito.times(30)).onNext(captor.capture());
for (Integer value : captor.getAllValues()) {
System.out.println(value);
}
}
答案 3 :(得分:0)
您如何看待这一点,当然我正在打电话时,我已经成为我的API的一部分:
public class StreamOfSomething {
new StreamOfSomething() {
// source of events like
events = Observable.range(0, 1_000_000_000)
.doOnNext(set::add) // some operation there
.map(Event::change)
.publish()
.refCount();
}
public Observable<Event> observeChanges() {
return events.startWith(
Observable.just(Event.snapshot(set))); // start stream with generated event
}
}
客户端可以执行以下操作:
Observable.timer(2, 4, TimeUnit.SECONDS)
.limit(2)
.flatMap(t -> theSourceToWatch.observeChanges().limit(10))
.subscribe(System.out::println);
但是请注意,如果您处于多线程环境中,则在订阅阻止任何修改时可能需要进行同步,否则列表可能会在发出之前发生更改。或者完全围绕可观察者重写这个课程,但我还不知道如何实现这个目标。
答案 4 :(得分:0)
很抱歉在2年后发布,但我有同样的需求,发现这个问题没有答案。
我所做的是以下内容:
public Observable<Event> observe() {
return Observable.defer(() ->
subject.startWith(createInitialEvent())
);
}
这个想法如下:
所以,如果我回到原帖: 如果观察者在事件1,2之间开始订阅,那么它应该收到以下事件:InitialEvent,2,3,4,5。