RxJava:如何返回正确的null类型

时间:2017-08-21 03:06:42

标签: android firebase firebase-authentication kotlin rx-java

我正在使用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()

当用户选择照片时它正常工作,但是当它没有被选中时,其他地图将被忽略,因为我返回了Maybe.empty()。

如果使用或不使用用户照片,我应该如何实现此功能?

感谢。

1 个答案:

答案 0 :(得分:1)

看一下以下构造:

        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()运算符返回将传递给下一个运算符链的默认值,而不跳转到onErrorObserver

所以你的代码应该是这样的:

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

                }
...
...

希望它有所帮助。