Firestore (Kotlin) 在执行文档请求时将完整任务转换为密封 class 的正确方法
Firestore (Kotlin) proper way to convert a complete task into a sealed class when performing a document request
我正在尝试一种正确的方法,将一个完整的任务转换成一个密封的 class 在对文档执行获取请求时易于阅读(此时我将在稍后看到集合请求).
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 为真时,我们确定 task.result 始终不为空吗?
提前致谢
对于这两个问题,请注意
当任务所代表的工作按预期完成且没有错误时,任务为 "successful"。另一方面,当 Task 代表的工作完成时,Task 是 "complete",而不管它是 "success" 还是 "failure"。可能有错误也可能没有错误,您必须检查一下。
一个已经成功完成的任务 returns 一个 DocumentSnapshot
将 永远不会 具有 null
的值。如果请求的文档不存在,您将得到一个空的 DocumentSnapshot 对象,而不是 null
。这也意味着如果您调用 exists()
:
documentSnapshot.exists() //Will returns false
如果正在调用 getData()
方法:
documentSnapshot.getData() //An exception will be thrown
如果 Taks 不是 "successful",则由 task.getException()
生成的异常是 FirebaseFirestoreException
的实例。请注意任务的 getException() 方法:
Returns the exception that caused the Task to fail. Returns null if the Task is not yet complete, or completed successfully.
我正在尝试一种正确的方法,将一个完整的任务转换成一个密封的 class 在对文档执行获取请求时易于阅读(此时我将在稍后看到集合请求).
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 为真时,我们确定 task.result 始终不为空吗?
提前致谢
对于这两个问题,请注意 当任务所代表的工作按预期完成且没有错误时,任务为 "successful"。另一方面,当 Task 代表的工作完成时,Task 是 "complete",而不管它是 "success" 还是 "failure"。可能有错误也可能没有错误,您必须检查一下。
一个已经成功完成的任务 returns 一个 DocumentSnapshot
将 永远不会 具有 null
的值。如果请求的文档不存在,您将得到一个空的 DocumentSnapshot 对象,而不是 null
。这也意味着如果您调用 exists()
:
documentSnapshot.exists() //Will returns false
如果正在调用 getData()
方法:
documentSnapshot.getData() //An exception will be thrown
如果 Taks 不是 "successful",则由 task.getException()
生成的异常是 FirebaseFirestoreException
的实例。请注意任务的 getException() 方法:
Returns the exception that caused the Task to fail. Returns null if the Task is not yet complete, or completed successfully.