如何在RxJava 2和Kotlin中将null传递给具有可空类型的Observable

Abh*_*air 14 android kotlin rx-java rx-kotlin rx-java2

我像这样初始化我的变量: -

 val user: BehaviorSubject<User?> user = BehaviorSubject.create()
Run Code Online (Sandbox Code Playgroud)

但我不能这样做.IDE抛出错误: -

user.onNext(null)
Run Code Online (Sandbox Code Playgroud)

这样做,IDE说你永远不会为空: -

user.filter( u -> u!=null)
Run Code Online (Sandbox Code Playgroud)

nha*_*man 12

正如Guenhter解释的那样,这是不可能的.但是,我不建议使用null-object模式,而是建议使用以下Optional类型的实现:

data class Optional<T>(val value: T?)
fun <T> T?.asOptional() = Optional(this)
Run Code Online (Sandbox Code Playgroud)

这使您的意图更加清晰,您可以在函数中使用解构声明:

Observable.just(Optional("Test"))
  .map { (text: String?) -> text?.substring(1)?.asOptional() }
  .subscribe()
Run Code Online (Sandbox Code Playgroud)

在这里使用null-object模式可能会导致比它解决的更多错误.

  • `Optional`(使用`java.util.Optional`等方法)的"完整"实现非常简短:https://gist.github.com/ephemient/2dec1165b7993e6a6cd7cdfa005fe277 (3认同)

gue*_*ter 9

如果您使用rxkotlin/rxjava 2.0(我假设如此),答案是:您不能.这里解释了原因.

这是界面的中断.看看Observable界面

public interface Observer<T> {

    /** ... */
    void onSubscribe(@NonNull Disposable d);

    /** ... */
    void onNext(@NonNull T t);

    /** ... */
    void onError(@NonNull Throwable e);

    /** ... */
    void onSubscribe(@NonNull Disposable d);

    /** ... */
    void onNext(@NonNull T t);

    /** ... */
    void onError(@NonNull Throwable e);
...
Run Code Online (Sandbox Code Playgroud)

@NonNull将由Kotlin编译器考虑,因此您不能传递null.

即使你可以,onNext也会立即抛出一个错误:

@Override
public void onNext(T t) {
    if (t == null) {
        onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
        return;
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果你真的需要这样的东西,null你必须伪造它.例如,通过创建一个静态对象User来表示你的null元素.

例如

data class User(val username, val password) {

    companion object {
        val NULL_USER = User("", "")
    }
}
...
val user = BehaviorSubject.create<User>()
...
user.onNext(User.NULL_USER)
...
user.filter { it !== User.NULL_USER }
Run Code Online (Sandbox Code Playgroud)

但它在某种程度上是可能的,尽量避免这个null概念,并且可能想到另一个不需要这个的解决方案.


Abh*_*air 4

非常感谢您的所有回答,但我最终选择了这个解决方案:-

class UserEnvelope(val user:User?) {}
Run Code Online (Sandbox Code Playgroud)

并在可观察量中使用它。

这最适合我的要求。

我是 Kotlin 新手,所以我不知道如何使用Options。但根据我的理解,每次我需要观察值时,我都必须将其类型转换为 User 类型,对吗?