我正在使用Firebase,Kotlin和RxJava开发应用程序。

基本上,我需要做的是使用Firebase中的Auth注册用户,如果用户选择了照片,请上传照片,然后将用户从Firebase中保存到数据库中。

到现在为止

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()

当用户选择照片时,它可以正常工作,但是当未选择照片时,其他 map 将被忽略,因为我返回了Maybe.empty()。

无论有没有用户照片,我应该如何实现?

谢谢。

最佳答案

看一下下面的构造:

        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");
                })

如果遇到null,则应该抛出错误,然后使用onErrorReturn{}onErrorReturnItem()运算符返回默认值,该默认值将传递到下一个运算符链,而无需跳转到onError中的Observer

因此,您的代码应如下所示:
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()

但是此代码存在一个问题,即在onErrorReturn之前发生的任何异常都会产生空白uri,并导致我们不希望执行进一步的链执行。如果发生任何其他异常,则应调用onError。

为此,我们需要创建一个自定义Exception类,并在onErrorReturn中捕获此引发的异常。看看以下片段:
...
...

.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

                }
...
...

希望能帮助到你。

07-24 04:04