I have a Sign-Up Screen. On that screen, I get Username, Email, and Password. The Firestore API automatically checks if the Email is in use or not but I want to show the user if the Username entered is in use or not. To do it I used this code snippet :
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
but here it skips and continues without returning the correct value. When I try this separately it works fine I understand if data exists or not but when I use it like this it doesn’t work. I have tried adding await() but it also has not worked. To run it under @Composable function I made the function suspend first after that I called this userExists function under rememberCoroutine but also couldn’t run it. The thing I want is simply checking for example userName: user1234 exists or not.
Thanks in advance.
Edit : Whole code.
@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")
}
}
}
3
Answers
Before @Faruk Karaca's answer I solved the problem. I am specifying this because it may work as well idk.
Here is the whole code :
Under mainScope.launch I implemented my suspend function.
You cannot return
isExists
as a result of a function. Firebase API is asynchronous. To solve this, you have to use a solution that is always the same. Any code that needs data from Firestore, needs to be inside theonSuccess()
function or be called from there. However, a more modern approach will be to use Kotlin Coroutines.This sentence doesn’t provide enough information so we can help. However, when you call await() it means that it will always await the completion of the task without blocking a thread. Please note that this function is a
suspend
function and not ablocking
function. So your function should look like this:This method will check if the result of the query is empty or not.
You can’t do it this way because it’s an asynchronous operation. Bu you can do it like this using flow and suspend functions.
And collect like this,