You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin中传递Firestore查询以在Helper函数的when块区分处理?

解决Firestore查询复用与分支判断问题

你当前代码的核心问题在于,handleQuery的when条件中每次调用db.collection("Users").document(user!!.uid).get()都会生成一个全新的Task<DocumentSnapshot>实例,和传入的query对象引用完全不同,因此永远无法匹配到对应的分支逻辑。

以下是两种可行的解决方案:

方案一:枚举类标识查询类型(适合统一管理查询场景)

这种方式通过枚举定义所有查询类型,将查询任务与类型绑定,让handleQuery能通过枚举值区分处理逻辑。

  1. 定义查询类型枚举
enum class FirestoreQueryType {
    GET_USER_PROFILE
    // 后续新增查询场景直接添加枚举值即可
}
  1. 封装查询任务与类型的实体类
data class TypedFirestoreQuery(
    val task: Task<DocumentSnapshot>,
    val type: FirestoreQueryType
)
  1. 修改query辅助函数
fun query(typedQuery: TypedFirestoreQuery, auth: FirebaseAuth) {
    typedQuery.task.addOnCompleteListener { dbTask ->
        if (dbTask.isSuccessful) {
            val userDoc = dbTask.result
            val exists = userDoc?.exists() ?: false
            handleQuery(typedQuery.type, auth, exists)
        } else {
            Log.d("TAG", "Error: ", dbTask.exception)
        }
    }
}
  1. 重构handleQuery函数
private fun handleQuery(queryType: FirestoreQueryType, auth: FirebaseAuth, exists: Boolean = false) {
    val user = auth.currentUser ?: return // 提前处理null,避免非空断言!!
    
    when (queryType) {
        FirestoreQueryType.GET_USER_PROFILE -> {
            if (exists) {
                Log.i("TAG", "User already exists.")
            } else {
                Log.e("TAG", "User doesn't exist in db. Attempting to add...")
                db.collection("Users")
                    .document(user.uid)
                    .set(hashMapOf(
                        "uid" to user.uid,
                        "name" to user.displayName,
                        "email" to user.email,
                        "photoURL" to user.photoUrl
                    ))
                Log.i("TAG", "User has been added")
            }
        }
    }
}
  1. 调用方式
val getUserQuery = TypedFirestoreQuery(
    task = db.collection("Users").document(user!!.uid).get(),
    type = FirestoreQueryType.GET_USER_PROFILE
)
utils.query(getUserQuery, auth)

方案二:高阶函数传递处理逻辑(灵活适配不同查询)

如果每个查询的处理逻辑差异较大,不需要统一管理,直接将成功/失败的处理逻辑作为参数传入辅助函数会更简洁。

  1. 修改query辅助函数
fun query(
    task: Task<DocumentSnapshot>,
    onSuccess: (DocumentSnapshot?, Boolean) -> Unit,
    onFailure: (Exception) -> Unit
) {
    task.addOnCompleteListener { dbTask ->
        if (dbTask.isSuccessful) {
            val userDoc = dbTask.result
            val exists = userDoc?.exists() ?: false
            onSuccess(userDoc, exists)
        } else {
            dbTask.exception?.let(onFailure) ?: Log.d("TAG", "Unknown error occurred")
        }
    }
}
  1. 调用方式
utils.query(
    task = db.collection("Users").document(user!!.uid).get(),
    onSuccess = { _, exists ->
        val currentUser = auth.currentUser ?: return@query
        if (exists) {
            Log.i("TAG", "User already exists.")
        } else {
            Log.e("TAG", "User doesn't exist in db. Attempting to add...")
            db.collection("Users")
                .document(currentUser.uid)
                .set(hashMapOf(
                    "uid" to currentUser.uid,
                    "name" to currentUser.displayName,
                    "email" to currentUser.email,
                    "photoURL" to currentUser.photoUrl
                ))
            Log.i("TAG", "User has been added")
        }
    },
    onFailure = { exception ->
        Log.d("TAG", "Error: ", exception)
    }
)

内容的提问来源于stack exchange,提问作者Connor Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 05:27:27