Firestore (Kotlin) правильный способ конвертировать завершенную задачу в запечатанный класс при выполнении запроса документа

Я пытаюсь поэкспериментировать с правильным способом преобразования полной задачи в запечатанный класс, легко читаемый при выполнении запроса get к документу (в данный момент и позже я увижу запрос коллекций).

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) Можем ли мы разумно убедиться, что Task.exception всегда не равен NULL и экземпляр FirebaseFirestoreException, когда isSuccessFul имеет значение false?

2) Мы уверены, что task.result всегда не равен нулю, когда task.isSuccessful имеет значение true?

заранее спасибо

1 ответ

Решение

Для обоих вопросов, пожалуйста, обратите внимание, что Задание является "успешным", когда работа, представленная заданием, завершена, как ожидается, без ошибок. С другой стороны, Задача является "завершенной", когда работа, представленная Задачей, завершена, независимо от ее "успеха" или "неудачи". Там может быть или может быть или не быть ошибкой, вам придется проверить это.

Уже успешно выполненная задача возвращает DocumentSnapshot который никогда не будет иметь значения null, Если запрошенный документ не существует, вы получите пустой объект DocumentSnapshot, а не null, Это также означает, что если вы позвоните exists():

documentSnapshot.exists() //Will returns false

А если звонят getData() метод:

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

Если Такс не "успешен", исключение, которое выбрасывается task.getException() это экземпляр FirebaseFirestoreException, Обратите внимание, что метод getException () в Task:

Возвращает исключение, которое вызвало сбой Задачи. Возвращает ноль, если Задача еще не завершена или успешно завершена.

Другие вопросы по тегам