firebase 如何使用Jetpack Compose检查Firestore数据库中的值是否存在?

ve7v8dk2  于 2023-10-22  发布在  其他
关注(0)|答案(3)|浏览(197)

我有一个注册屏幕。在那个屏幕上,我得到了电子邮件,电子邮件和密码。Firestore API会自动检查电子邮件是否在使用中,但我想向用户显示输入的电子邮件是否在使用中。为此,我使用了以下代码片段:

fun userExists(element1 : String, element2 : String) : Boolean {

val db : FirebaseFirestore = FirebaseFirestore.getInstance()
val dbUsers : CollectionReference = db.collection("user")
var isExists : Boolean = false

dbUsers.whereEqualTo(element1, element2).get().addOnSuccessListener {
    // if true it is empty and it is not exists.
    isExists = it.documents.isNotEmpty()
}
return isExists

但在这里它跳过并继续,而不返回正确的值。当我单独尝试时,它工作得很好,我知道数据是否存在,但当我这样使用它时,它不工作。我尝试添加await(),但它也没有工作。为了在@Composable函数下运行它,我先让函数挂起,然后在rememberCoroutine下调用了这个userlogists函数,但也无法运行它。我想要的只是检查例如userName:user 1234是否存在。先谢了。
编辑:整个代码。

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SignUpScreen(navigation: NavController, auth: FirebaseAuth) {
    var userName by remember { mutableStateOf("") }
    var userEmail by remember { mutableStateOf("") }
    var password by rememberSaveable { mutableStateOf("") }
    var passwordVisible by rememberSaveable { mutableStateOf(false) }
    val context = LocalContext.current
    val sharedPrefMail = context.getSharedPreferences("userEmail", Context.MODE_PRIVATE)
    val sharedPrefName = context.getSharedPreferences("userName", Context.MODE_PRIVATE)
    val sharedPrefScore = context.getSharedPreferences("highScore", Context.MODE_PRIVATE)
    val db : FirebaseFirestore = FirebaseFirestore.getInstance()
    val dbUsers : CollectionReference = db.collection("user")

    val buttonSize = with(LocalDensity.current) {
        (300f).toDp()
}
Column(
    modifier = Modifier
        .fillMaxSize()
        .padding(vertical = buttonSize),
    horizontalAlignment = Alignment.CenterHorizontally
) {
    {...}
    // Toast message is not shown. Use PopUp message
    Button(onClick = {

        if (userEmail == "" || password == "" || userName == "") {
            Toast.makeText(context, "PLEASE ENTER EMAIL, USERNAME AND PASSWORD", Toast.LENGTH_LONG).show()
        } else if (userExists("userName", userName)) {
            Toast.makeText(context, "USERNAME IS IN USE", Toast.LENGTH_LONG).show()
        } else {
            auth.createUserWithEmailAndPassword(userEmail, password).addOnSuccessListener {
                // User creation is successful
                val user = UserObj(userEmail, userName, "0")
                dbUsers.add(user).addOnSuccessListener {
                    Toast.makeText(context, "USER CREATED SUCCESSFULLY", Toast.LENGTH_LONG).show()
                    sharedPrefMail.edit().putString("userMail", userEmail).apply()
                    sharedPrefName.edit().putString("userName", userName).apply()
                    sharedPrefScore.edit().putString("highScore", "0").apply()
                }
                navigation.navigate("FirstScreen")
            }.addOnFailureListener {
                Toast.makeText(context, "COULDN'T CREATE USER", Toast.LENGTH_LONG).show()
                println(it.localizedMessage)
            }

        }

    },
        modifier = Modifier.size(buttonSize, buttonSize/3)
    ) {
        Text("SIGN UP")
    }
}
}
avwztpqn

avwztpqn1#

不能将isExists作为函数的结果返回。Firebase API是异步的。为了解决这个问题,你必须使用一个总是相同的解决方案。任何需要从Firestore获取数据的代码都需要在onSuccess()函数内部或从那里调用。然而,更现代的方法是使用Kotlin Coroutines
我尝试添加await(),但它也不起作用。
这句话没有提供足够的信息,所以我们可以帮助。然而,当你调用await()时,它意味着它将一直等待任务的完成,而不会阻塞线程。请注意,此函数是suspend函数,不是blocking函数。所以你的函数应该看起来像这样:

fun userExists(element1 : String, element2 : String) : Boolean {
    val db: FirebaseFirestore = FirebaseFirestore.getInstance()
    val dbUsers: CollectionReference = db.collection("user")

    return dbUsers.whereEqualTo(element1, element2).get().await().isEmpty
}

这个方法将检查查询的结果是否为空。

2ul0zpep

2ul0zpep2#

你不能这样做,因为这是一个异步操作。但是你可以用flow和suspend函数来做。

suspend fun isUserExists(element1: String, element2: String) = callbackFlow {
        try {
            val db: FirebaseFirestore = FirebaseFirestore.getInstance()
            val dbUsers: CollectionReference = db.collection("user")

            dbUsers.whereEqualTo(element1, element2).get()
                .addOnSuccessListener {
                    trySendBlocking(it.documents.isNotEmpty())
                }.addOnFailureListener {
                    // your error action
                }

        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

像这样收集,

viewModel.isUserExists().collect { isUserNameExist ->
    //
}
yyhrrdl8

yyhrrdl83#

在@Faruk Karaca的回答之前,我解决了这个问题。我指定这一点,因为它可能工作以及idk。
下面是整个代码:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SignUpScreen(navigation: NavController, auth: FirebaseAuth) {
    val db : FirebaseFirestore = FirebaseFirestore.getInstance()
    val dbUsers : CollectionReference = db.collection("user")

    val mainScope = rememberCoroutineScope()

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(vertical = buttonSize),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        
        Button(onClick = {
            mainScope.launch(Dispatchers.Main) { // important
                if (userEmail == "" || password == "" || userName == "") {
                    Toast.makeText(context, "PLEASE ENTER EMAIL, USERNAME AND PASSWORD", Toast.LENGTH_LONG).show()
                } else if (userExists("userName", userName)) {
                    Toast.makeText(context, "USERNAME IS IN USE", Toast.LENGTH_LONG).show()
                } else {
                    auth.createUserWithEmailAndPassword(userEmail, password).addOnSuccessListener {
                        val user = UserObj(userEmail, userName, "0")
                        dbUsers.add(user).addOnSuccessListener {
                            // Successful processes
                        }
                        navigation.navigate("FirstScreen")
                    }.addOnFailureListener {
                        //Failure processes
                    }
                }
            }
        },
            modifier = Modifier.size(buttonSize, buttonSize/3)
        ) {
            Text("SIGN UP")
        }
    }
    }

suspend fun userExists(element1 : String, element2 : String) : Boolean {
    val db : FirebaseFirestore = FirebaseFirestore.getInstance()
    val dbUsers : CollectionReference = db.collection("user")

    return !dbUsers.whereEqualTo(element1, element2).get().await().isEmpty

}

在mainScope.launch下我实现了我的suspend函数。

相关问题