0

我正在尝试一种正确的方法,在对文档执行获取请求时将完整的任务转换为易于阅读的密封类(此时,我将在稍后看到集合请求)。

import com.google.android.gms.tasks.Task
import com.google.firebase.firestore.DocumentSnapshot
import com.google.firebase.firestore.FirebaseFirestoreException
import timber.log.Timber

fun <T> Task<DocumentSnapshot?>.toDocumentResult(parser: (documentSnapshotExisting: DocumentSnapshot) -> T): DocumentResult<T>?{
    val documentResult: DocumentResult<T> = if(isSuccessful){
        val documentSnapshot: DocumentSnapshot = result!!
        if(documentSnapshot.exists()){
            try {
                DocumentResult.Found(parser.invoke(documentSnapshot))
            }
            catch (e: java.lang.Exception){
                DocumentResult.ParserException<T>(documentId = documentSnapshot.id, e = e)
            }
        }else{
            DocumentResult.NotFound(documentSnapshot.id)
        }
    }else{
        DocumentResult.Error(exception!! as FirebaseFirestoreException)
    }
    documentResult.log()
    return documentResult
}


sealed class DocumentResult<T>{
    abstract fun log()

    class Found<T>(val o: T): DocumentResult<T>() {
        override fun log() {
            Timber.tag("DocumentResult").w("$o")
        }
    }

    class NotFound<T>(val documentId: String): DocumentResult<T>() {
        override fun log() {
            Timber.tag("DocumentResult").w("documentId: $documentId doesn't exist")
        }
    }

    class ParserException<T>(val documentId: String, val e: Exception): DocumentResult<T>() {
        override fun log() {
            Timber.tag("DocumentResult").e("ParserException: ${e.localizedMessage?:e.message?:"error"}, documentId: $documentId")
        }
    }

    class Error<T>(val e: FirebaseFirestoreException): DocumentResult<T>() {
        override fun log() {
            Timber.tag("DocumentResult").e("FirebaseFirestoreException - code: ${e.code.name}, ${e.localizedMessage?:e.message?:"error"}")
        }
    }
}

有了这个片段,我可以这样做:

activity.firestore.documentAvailableLanguages().get().addOnCompleteListener { task ->
    val documentResult = task.toDocumentResult { AvailableLanguages.toObject(it) }
    when(documentResult){
        is DocumentResult.Found -> { /* My converted object */ }
        is DocumentResult.NotFound -> {  /* document not found */}
        is DocumentResult.Error-> {  /* FirebaseFirestoreException */}
        is DocumentResult.ParserException -> { /* Conversion didn't work, exception */ }
    }
}

我的问题是:

1)当 isSuccessFul 为 false 时,我们能否合理地确保 Task.exception 始终不为 null 且 FirebaseFirestoreException 的实例?

2)当 task.isSuccessful 为 true 时,我们确定 task.result 始终不为空吗?

提前致谢

4

1 回答 1

0

对于这两个问题,请注意,当任务所代表的工作按预期完成且没有错误时,该任务是“成功的”。在顺序方面,当 Task 所代表的工作完成时,Task 即为“完成”,而不管其“成功”或“失败”。可能有错误,也可能没有错误,你必须检查一下。

一个已经成功完成的任务返回一个DocumentSnapshot永远不会有 的值null。如果请求的文档不存在,您将获得一个空的 DocumentSnapshot 对象 not null。这也意味着如果你打电话exists()

documentSnapshot.exists() //Will returns false

如果正在调用getData()方法:

documentSnapshot.getData() //An exception will be thrown

如果 Taks 不是“成功的”,则 Exceptiontask.getException()是一个 instanceof FirebaseFirestoreException。请注意 Task 的getException()方法:

返回导致任务失败的异常。如果任务尚未完成或成功完成,则返回 null。

于 2019-01-28T16:09:58.353 回答