Home > Net >  Alert Dialog positive button does not wait until Async Firestore request call completed?
Alert Dialog positive button does not wait until Async Firestore request call completed?

Time:03-08

I have AlertDialog with a custom layout to sign in users, which check if it is user's first time signing in by checking the Firestore for the existence of their email.

private fun showSignInDialog() {

     val builder: AlertDialog.Builder = AlertDialog.Builder(requireContext())
     builder.setTitle("Sign In")
     val inflater = requireActivity().layoutInflater
     val dialogView = inflater.inflate(R.layout.dialog_sign_in, null)
     builder.setView(dialogView)
     val editEmail = dialogView.findViewById<EditText>(R.id.edit_email)
     val editPassword = dialogView.findViewById<EditText>(R.id.edit_password)

     builder.setPositiveButton("OK") { _, _ ->
        val email = editEmail.text.toString()
        val password = editPassword.text.toString()
        signInWithEmail(email, password)
     }
     builder.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() }
     builder.create().show()
}

private fun signInWithEmail(email: String, password: String) {
     auth = Firebase.auth
     auth.signInWithEmailAndPassword(email, password)
            .addOnCompleteListener(requireActivity()) { task ->
                if (task.isSuccessful) {
                    Log.d(TAG, "signInWithEmail:success")
                    val signedInEmail = auth.currentUser?.email
                    firestoreService = FirestoreService()

                    firestoreService.doesUserAlreadyExists(object : UserCallback {
                        override fun onCallback(dRef: String) {
                            Log.d(TAG, "dRef = $dRef")
                            if (dRef.isEmpty())
                                findNavController().navigate(R.id.action_signIn_to_ceateProfile)
                            else
                                findNavController().navigate(R.id.action_signIn_to_main)
                        }
                    }, signedInEmail!!)
                } else {
                    // If sign in fails, display a message to the user.
                    Log.w(TAG, "signInWithEmail:failure", task.exception)
                    Toast.makeText(
                        requireContext(), "Authentication failed.",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
}

FirestoreService.kt

class FirestoreService {

    private val db = Firebase.firestore

    fun doesUserAlreadyExists(callback: UserCallback, email: String) {
        db.collection("Users")
            .whereEqualTo("email", email).get()
            .addOnSuccessListener { documents ->
                for (document in documents) {
                    val docRef = document.id
                    callback.onCallback(docRef)
                    Log.d(TAG, "docRef = $docRef")
                }
            }
            .addOnFailureListener { e ->
                Log.w(TAG, "Error adding User document", e)
            }
    }
}

But this doesUserAlreadyExists never get executed, this is probably because since this method is async and there is nothing to return to after the finish of async callback, since dialog is destroyed by that time. How could I make this work?

Update :

I tried same logic on fragments instead of dialogs, same outcome, It seems something have to do with the firestoreService.doesUserAlreadyExists inside the addOnCompleteListener since one async callback is inside an another async callback. How to fix this?

CodePudding user response:

Issue was there was no "Users" collection to check since I have deleted the "Users" collection so neither addOnSuccessListener or addOnFailureListener was called.

I wish there was an exception being thrown when a collection does not exist.

  • Related