我像这样初始化我的变量: -
val user: BehaviorSubject<User?> user = BehaviorSubject.create()
但我不能这样做。 IDE抛出错误: -
user.onNext(null)
这样做,IDE说你永远不会为空: -
user.filter( u -> u!=null)
正如Guenhter解释的那样,这是不可能的。但是,我建议实现Optional
类型,而不是提出null-object模式:
data class Optional<T>(val value: T?)
fun <T> T?.asOptional() = Optional(this)
这使您的意图更加清晰,您可以在函数中使用解构声明:
Observable.just(Optional("Test"))
.map { (text: String?) -> text?.substring(1)?.asOptional() }
.subscribe()
在这里使用null-object模式可能会导致比它解决的更多错误。
如果您使用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);
...
@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;
}
...
}
如果你真的需要像null
这样的东西你必须伪造它。例如通过创建一个代表你的User
元素的null
的静态对象。
EG
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 }
但它在某种程度上是可能的,试图避免null
概念,并可能想到另一种解决方案,这是不需要的。
非常感谢您的所有答案,但我最终选择了这个解决方案: -
class UserEnvelope(val user:User?) {}
并在观察中使用它。
这最符合我的要求。
我是Kotlin的新手,所以我不知道如何使用Optionals。但根据我的理解,每次我需要观察值时,我都必须将其类型化为用户类型?
由于RxJava 2不支持空值,因此您可以使用其他一些可接受的解决方案:
Any
类实例。例如,您可以创建一个Empty.INSTANCE
枚举类,它将模拟null值,然后按枚举类进行过滤。abstract class SessionUser
sealed class LoggedUser(val username: String, val password: String) : SessionUser()
sealed class LogoutUser : SessionUser()
private val user = BehaviorSubject.create<SessionUser>()
private val loggedUser =
user.filter { it is LoggedUser }.cast(LoggedUser::class.java)
fun login(username: String, password: String) {
user.onNext(LoggedUser(username, password))
}
fun logout() {
user.onNext(LogoutUser())
}