不传递任何东西到onNext()的Observable

46

例如,我需要一个Observable来提供一个系统时钟,它不需要在onNext()中传递任何内容。我找不到一个允许我这样做的签名。

当然,我可以使用任何对象然后传递null,但那没有太多意义。所以我的问题是是否有更好的方法来实现这一点。

Observable.create(new Observable.OnSubscribe<Anyobject>() { // use any object in the signature

            @Override public void call(Subscriber<? super Anyobject> subscriber) {

                    subscriber.onNext(null); // then pass null
                    subscriber.onCompleted();

            }

        })

所以你只想调用没有参数的onNext()函数吗? - david.mihola
2
对于其他人来说,需要注意的是,尽管其他答案和评论可能会说onNext(null)没问题,但实际上并不是这样。请参见规范。此外,请查看RxJava中的此问题 - Chad Retz
6个回答

46
如果您的Observable没有发出任何内容,那么您不需要调用onNext。您可以在签名中使用Void,并执行以下操作:
Observable<Void> o = Observable.create(new Observable.OnSubscribe<Void>() {
    @Override
    public void call(Subscriber<? super Void> subscriber) {
        // Do the work and call onCompleted when you done,
        // no need to call onNext if you have nothing to emit
        subscriber.onCompleted();
    }
});

o.subscribe(new OnCompletedObserver<Void>() {
    @Override
    public void onCompleted() {
        System.out.println("onCompleted");
    }

    @Override
    public void onError(Throwable e) {
        System.out.println("onError " + e.getMessage());
    }
});

您可以定义一个OnCompletedObserver来简化您的Observer回调,这样您就不必覆盖onNext,因为您不需要它。
public abstract class OnCompletedObserver<T> implements Observer<T> {
    @Override
    public void onNext(T o) {

    }
}

如果我理解您的问题,那么这应该可以解决问题。

1
我希望我的Observable发出一些东西,这是常规的滴答声,即使这个滴答声除了时间点之外没有任何其他东西(不需要传递对象)。使用Void的技巧很好,但我猜我不能在onNext(void)中传递void,因为Void无法实例化。不过我可以传递null,所以它可以很好地完成工作。谢谢! - Oliver Hausler
是的,你说得对,在那种情况下你可以简单地使用 null - Miguel
@MiguelLavigne,你能否更新一下你的答案?我知道它可以正常工作,但考虑到最近的API更新,也许我们可以用不同但更优雅的方式来实现它?谢谢! - beerBear
1
@beerBear同意需要修改这个答案,我会很快处理的,谢谢! - Miguel
6
在RxJava 2中不再允许使用null - BoD

43

如果你需要在调用 onCompleted() 之前将某些内容传递给 onNext()

Observable.<Void>just(null)

如果你只需要调用onCompleted()

Observable.empty()

遗留代码库中有很多方法使用 Observable<void> 作为返回类型。如果不需要执行任何操作,则传递 Observable.empty() 看起来是一个有效的选择。但是我在某些情况下遇到了问题,因为 Observable.empty() 会导致返回类型不匹配(Observable<?> 而不是 Observable<void>)。您的答案非常有帮助,因为我能够轻松地执行 Observable.<Void>empty() 而不需要做其他麻烦的事情。谢谢。 - Saurabh Shrivastava

13

RxJava 2 Wiki

RxJava 2.x 不再接受 null 值,下列代码会立即引发 NullPointerException 或者向下游发出信号。

...

这意味着 Observable<Void> 不再能够发射任何值,只能正常终止或出现异常。API 设计者可以选择定义不带任何保证的 Observable<Object>(实际上应该与 Object 类型无关)。

这意味着你不能使用 Void 并且执行 Observable.just(null)

请改用 Object 或其他简单类型代替:

Observable.just(new Object());

3

一种轻量级的解决方案是使用Observable<Boolean>

然后调用onNext(Boolean.TRUE),但是你可以忽略它。

但在这种情况下,可能不应该使用Observable。
考虑改用Completable


3
从RxJava 2开始,正确的做法是使用Completable来完成此操作。
文档中可以看到:
代表一个没有值的延迟计算,仅表示完成或异常。该类遵循与Reactive-Streams类似的事件模式:onSubscribe(onError|onComplete)?

0

我不知道这是否对你有帮助。
这段代码是用 RxSwift 编写的。

// Create an observable and emit somethings
let myObservable = Observable<Void>.create{ observer in
    observer.on(.next(Void()))
    return Disposables.create()
}

// Observer subscribe changes
myObservable.subscribe(onNext: {
    _ in
    print("Hello")
}).disposed(by: disposeBag)

或者使用变量对象

// Create a Variable object that contanins nothing
var myValueWatcher:Variable<Void> = Variable<Void>(Void())

// Observer subscribe changes
myValueWatcher.asObservable().skip(1).subscribe(onNext: {
    _ in
    print("Changes!")
}).disposed(by: disposeBag)


// The emit code
myValueWatcher.value = Void()

你可以将Void()替换为()。 - dduyduong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接