J'initialise ma variable comme ceci: -
val user: BehaviorSubject<User?> user = BehaviorSubject.create()
Mais je ne peux pas faire ça. IDE génère une erreur: -
user.onNext(null)
Et, faisant cela, IDE dit que vous ne serez jamais nul:
user.filter( u -> u!=null)
Merci beaucoup pour toutes vos réponses mais je suis finalement allé avec cette solution: -
class UserEnvelope (val user: utilisateur?) {}
Et en utilisant cela dans les observables.
Cela convenait le mieux à mes exigences.
Je suis nouveau à Kotlin, donc je ne sais pas utiliser Optionals. Mais de ce que je comprends, je devrais le transtyper en type d'utilisateur à chaque fois que je dois observer les valeurs non?
Comme Guenhter a expliqué, cela n’est pas possible. Cependant, au lieu de proposer le modèle null-object, je recommanderais une implémentation du type Optional
:
data class Optional<T>(val value: T?)
fun <T> T?.asOptional() = Optional(this)
Cela clarifie votre intention et vous pouvez utiliser une déclaration de déstructuration dans vos fonctions:
Observable.just(Optional("Test"))
.map { (text: String?) -> text?.substring(1)?.asOptional() }
.subscribe()
L'utilisation du modèle null-object ici peut causer plus de bogues qu'elle n'en résout.
Si vous utilisez rxkotlin/rxjava 2.0 (je suppose donc), la réponse est: vous ne pouvez pas. La raison est expliquée ici.
C'est une rupture de l'interface. Jetez un coup d'œil à l'interface 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);
...
Le @NonNull
sera pris en compte par le compilateur Kotlin et par conséquent, vous NE POUVEZ PAS transmettre la valeur null.
Même si vous le pouviez, la onNext
lirait immédiatement une erreur:
@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;
}
...
}
Si vous avez vraiment besoin d'une chose comme null
, vous devez la simuler. par exemple. en créant un objet statique de User
qui représente votre null
- élément.
par exemple.
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 }
Mais il est possible, essayez d'éviter le concept null
et pensez peut-être à une autre solution qui ne serait pas nécessaire.
Étant donné que RxJava 2 ne prend pas en charge les valeurs null , vous pouvez utiliser d’autres solutions acceptables:
Any
avec votre type de sujet. Par exemple, vous pouvez créer une classe Empty.INSTANCE
enum qui émule la valeur null puis filtre par la classe enum.Le dernier est celui que j'utilise et préfère être une variante de la solution précédente et est basé sur des spécialisations. Nos amis de JetBrains insistent toujours sur le fait que les cours sont très peu coûteux à Kotlin. Ce serait donc un exemple rapide permettant de distinguer les utilisateurs connectés des utilisateurs non connectés:
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())
}