我有一个ObservableTransformer由几个合并在一起的子流组成,如下例所示。
ObservableTransformer<Action, Result> actionsToResults =
actions -> actions.publish(shared ->
Observable.merge(
Observable.merge(
shared.ofType(SendMessageAction.class).compose(sendMessageTransformer),
shared.ofType(CheckMessageInputAction.class).compose(checkIfEmptyTransformer)),
model.messagesObservable
.observeOn(AndroidSchedulers.mainThread())
)).replay(1).autoConnect();
// ╔════╗
// ╔══╣ ╠══╗
// ══╣ ╚════╝ ╠══(replay)>
// ╚══════════╝
我正在重放最后发出的元素,但我想要的是单独重放流。像这样:
// ╔════╗
// ╔══╣ ╠═(replay)═╗
// ══╣ ╚════╝ ╠══>
// ╚═════════(replay)═╝
因此,当我订阅整个流时,它会发出这两个内部流的最后一个元素。可以这样做吗?
编辑:为了使我的问题更清楚,我将扩展我认为问题所在。
我希望整个流是一个可连接的可观察对象。这很重要,因为它存在于无头片段内,并且不应该在旋转时重新触发所有调用。同时我想单独重播这些流。在外部合并中移动.replay(1).autoConnect()
将不起作用。将在每个新订阅时重新创建整个流。在外部合并中添加自定义运算符,如:
private ObservableTransformer<Action, Result> actionsToResults =
actions -> actions.publish(shared -> Observable.merge(Observable.merge(
shared.ofType(SendMessageAction.class).compose(sendMessageTransformer),
shared.ofType(CheckMessageInputAction.class).compose(checkIfEmptyTransformer)).lift(new ReplayLastOperator<Result>())
model.messagesObservable.lift(new ReplayLastOperator<>()).observeOn(AndroidSchedulers.mainThread())
));
ReplayLastOperator<Result>()
重放每个新订阅的最后一个元素相当于移动replay(1).autoConnect()
,在每个新订阅时重新创建整个流。所以没有什么可以重播的。最后一个.publish().autoConnect()
的解决方案只会订阅内部流一次,因此我无法检测到上游的新订阅,因此重放也不起作用。
我已经没有想法了。
答案 0 :(得分:0)
是。
您可以创建一个自定义运算符来缓存它看到的最后一项。
然后,当从上游收到onComplete时,它会重新发出它在发出onComplete之前看到的最后一项。该运算符的通用形式如下所示:
public class ReplayLast <T> implements ObservableOperator<T, T> {
@Override
public Observer<? super T> apply(@NonNull final Observer<? super T> observer) throws Exception {
return new Observer<T>(){
Disposable disposable;
T lastItem; // cache for last item
@Override
public void onSubscribe(@NonNull Disposable d) {
disposable = d;
observer.onSubscribe(d);
}
@Override
public void onNext(@NonNull T t) {
lastItem = t; // cache each item from up stream
observer.onNext(t); // emit as usual
}
@Override
public void onError(@NonNull Throwable e) {
observer.onError(e);
}
@Override
public void onComplete() {
if(lastItem != null){
// use the cache to emit the item again before signaling the complete downstream
observer.onNext(lastItem);
}
observer.onComplete();
}
};
}
然后只是在适当的地方使用它。应该类似于以下内容:
ObservableTransformer<Action, Result> actionsToResults =
actions -> actions.publish(shared ->
Observable.merge(
Observable.merge(
shared.ofType(SendMessageAction.class).compose(sendMessageTransformer),
shared.ofType(CheckMessageInputAction.class).compose(checkIfEmptyTransformer)).lift(new ReplayLast()),
model.messagesObservable.lift(new ReplayLast())
.observeOn(AndroidSchedulers.mainThread())
)).autoConnect();
答案 1 :(得分:0)
对于我的具体案例,我解决了这个问题。我将添加一些额外的信息,以便您了解它是否适用于您的情况。
在我的例子中,我想要重放的所有流都返回一个不同类型的对象,由一个抽象类密封。所以我对这个问题的解决方案是实现我自己的ObservableTransoformer
,名为ReplayLastByClassType
,它在地图中兑现按类型接收的最后一个元素。您只需致电.compose(ReplayLastByClassType.<SealingClass>instance()
或仅ReplayLastByClassType.instance()
即可申请。
变换器在订阅时重新发出兑现值。之后,它会继续传递连续onNext
次呼叫的元素。
即使您要重播的流返回相同类型的对象,此方法也可能对您有用。您必须将结果包装到单独的帮助程序类中以强制按类分离。
最后是定制的ObservableTransformer
,快乐的复制粘贴:)
public final class ReplayLastByClassType<T> implements ObservableTransformer<T, T> {
private static final ReplayLastByClassType<Object> INSTANCE = new ReplayLastByClassType<>();
/** The singleton instance of this transformer **/
@SuppressWarnings("unchecked")
public static <T> ReplayLastByClassType<T> instance() {
return (ReplayLastByClassType<T>) INSTANCE;
}
private ReplayLastByClassType() {
}
@Override
public Observable<T> apply(Observable<T> upstream) {
LastSeen<T> lastSeen = new LastSeen<>();
return new LastSeenObservable<>(upstream.doOnNext(lastSeen).publish().autoConnect(), lastSeen);
}
static final class LastSeen<T> implements Consumer<T> {
ConcurrentHashMap<Class, T> values = new ConcurrentHashMap<>();
@Override public void accept(T latest) {
values.put(latest.getClass(), latest);
}
}
static final class LastSeenObservable<T> extends Observable<T> {
private final Observable<T> upstream;
private final LastSeen<T> lastSeen;
LastSeenObservable(Observable<T> upstream, LastSeen<T> lastSeen) {
this.upstream = upstream;
this.lastSeen = lastSeen;
}
@Override
protected void subscribeActual(Observer<? super T> observer) {
upstream.subscribe(new LastSeenObserver<T>(observer, lastSeen));
}
}
static final class LastSeenObserver<T> implements Observer<T> {
private final Observer<? super T> downstream;
private final LastSeen<T> lastSeen;
LastSeenObserver(Observer<? super T> downstream, LastSeen<T> lastSeen) {
this.downstream = downstream;
this.lastSeen = lastSeen;
}
@Override public void onSubscribe(Disposable d) {
downstream.onSubscribe(d);
Map<Class, T> values = lastSeen.values;
for (T t: values.values()) {
downstream.onNext(t);
}
}
@Override public void onNext(T value) {
downstream.onNext(value);
}
@Override public void onComplete() {
downstream.onComplete();
}
@Override public void onError(Throwable e) {
downstream.onError(e);
}
}
}
PS:如果您在代码中看到任何错误,请在评论中纠正我。