2017-08-21 2 views
3

Je développe une application en utilisant Firebase, Kotlin et RxJava. Fondamentalement, ce que je dois faire est d'enregistrer un utilisateur en utilisant Auth de Firebase, si l'utilisateur a sélectionné une photo, télécharger la photo, puis enregistrer l'utilisateur dans la base de données de Firebase.RxJava: comment retourner le bon type de null

Jusqu'à présent j'avoir cette

RxFirebaseAuth.createUserWithEmailAndPassword(auth, email, password) 
      .map { authResult -> 
       user.uid = authResult.user.uid 
       authResult.user.uid 
      } 
      .flatMap<UploadTask.TaskSnapshot>(
        { uid -> 
         if (imageUri != null) 
          RxFirebaseStorage.putFile(mFirebaseStorage 
            .getReference(STORAGE_IMAGE_REFERENCE) 
            .child(uid), imageUri) 
         else 
          Maybe.empty<UploadTask.TaskSnapshot>() 
        } 
      ) 
      .map { taskSnapshot -> user.photoUrl = taskSnapshot.downloadUrl!!.toString() } 
      .map { 
       RxFirebaseDatabase 
         .setValue(mFirebaseDatabase.getReference("user") 
           .child(user.uid), user).subscribe() 
      } 
      .doOnComplete { appLocalDataStore.saveUser(user) } 
      .toObservable() 

Il fonctionne correctement lorsque l'utilisateur sélectionne une photo, mais quand il est pas sélectionné, les autres cartes sont ignorées, parce que je suis retourné Maybe.empty().

Comment dois-je mettre en œuvre que cela fonctionne avec ou sans photo d'utilisateur?

Merci.

Répondre

1

Jetez un oeil à Construct suivant:

 val temp = null 
     Observable.just("some value") 
       .flatMap { 
        // Throw exception if temp is null 
        if (temp != null) Observable.just(it) else Observable.error(Exception("")) 
       } 
       .onErrorReturnItem("") // return blank string if exception is thrown 
       .flatMap { v -> 
        Single.create<String>{ 
         // do something 
         it.onSuccess("Yepeee $v"); 
        }.toObservable() 
       } 
       .subscribe({ 
        System.out.println("Yes it worked: $it"); 
       },{ 
        System.out.println("Sorry: $it"); 
       }) 

Vous devriez jeter une erreur si vous rencontrez un null, puis utilisez onErrorReturn{} ou onErrorReturnItem() opérateur pour renvoyer une valeur par défaut qui sera transmis à la prochaine chaîne opérateur sans saut à onError dans Observer.

Donc, votre code devrait ressembler à ceci:

RxFirebaseAuth.createUserWithEmailAndPassword(auth, email, password) 
       .map { authResult -> 
        user.uid = authResult.user.uid 
        authResult.user.uid 
       } 
       .flatMap<UploadTask.TaskSnapshot>(
         { uid -> 
          if (imageUri != null) 
           RxFirebaseStorage.putFile(mFirebaseStorage 
             .getReference(STORAGE_IMAGE_REFERENCE) 
             .child(uid), imageUri) 
          else 
           Observable.error<Exception>(Exception("null value")) // Throw exception if imageUri is null 
         } 
       ) 
       .map { taskSnapshot -> user.photoUrl = taskSnapshot.downloadUrl!!.toString() } 
       .onErrorReturn { 
        user.photoUrl = "" // assign blank url string if exception is thrown 
       } 
       .map { 
        RxFirebaseDatabase 
          .setValue(mFirebaseDatabase.getReference("user") 
            .child(user.uid), user).subscribe() 
       } 
       .doOnComplete { appLocalDataStore.saveUser(user) } 
       .toObservable() 

Mais il y a un problème avec ce code que toute exception a eu lieu avant onErrorReturn céderais un uri blanc et entraîner une poursuite de l'exécution de la chaîne que nous ne voulons pas. Si une autre exception se produit, onError doit être appelé.

Pour cela, nous devons créer une classe personnalisée d'exception et attraper cette exception jeté onErrorReturn. Jetez un oeil à l'extrait suivant:

... 
... 

.flatMap<UploadTask.TaskSnapshot>(
         { uid -> 
          if (imageUri != null) 
           RxFirebaseStorage.putFile(mFirebaseStorage 
             .getReference(STORAGE_IMAGE_REFERENCE) 
             .child(uid), imageUri) 
          else 
           Observable.error<MyCustomException>(MyCustomException("null value")) // Throw exception if imageUri is null 
         } 
       ) 
       .map { taskSnapshot -> user.photoUrl = taskSnapshot.downloadUrl!!.toString() } 
       .onErrorReturn { 
        if(it !is MyCustomException) 
         throw it 
        else 
         user.photoUrl = "" // assign blank url string if exception is thrown 

       } 
... 
... 

Espérons que cela aide.

+1

Merci mon ami, il a travaillé comme un charme, vous m'a sauvé beaucoup de temps. – jackcar