警报对话框肯定按钮不会等到 Async Firestore 请求调用完成?
Alert Dialog positive button does not wait until Async Firestore request call completed?
我 AlertDialog
使用自定义布局来登录用户,它通过检查 Firestore 中是否存在用户的电子邮件来检查用户是否是第一次登录。
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)
}
}
}
但是这个 doesUserAlreadyExists
永远不会被执行,这可能是因为这个方法是异步的并且在异步回调完成之后没有什么可以 return 的,因为那时对话框已经被销毁了.我怎样才能完成这项工作?
更新:
我在片段而不是对话框上尝试了相同的逻辑,结果相同,这似乎与 addOnCompleteListener
中的 firestoreService.doesUserAlreadyExists
有关,因为一个异步回调在另一个异步回调中。如何解决这个问题?
问题是没有要检查的“用户”集合,因为我删除了“用户”集合,所以 addOnSuccessListener
或 addOnFailureListener
都没有被调用。
我希望在集合不存在时抛出异常。
最好使用 addOnCompleteListener
而不是 addOnSuccessListener
侦听器,因为它保证无论如何都会被触发
例如:
db.collection(USER_COLLECTION)
.whereEqualTo("email", email).get()
.addOnCompleteListener { task ->
if(task.isSuccessful){
for (document in task.result) {
if (document.exists()) {
//..
}
}
}
else{
//..
}
}
我 AlertDialog
使用自定义布局来登录用户,它通过检查 Firestore 中是否存在用户的电子邮件来检查用户是否是第一次登录。
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)
}
}
}
但是这个 doesUserAlreadyExists
永远不会被执行,这可能是因为这个方法是异步的并且在异步回调完成之后没有什么可以 return 的,因为那时对话框已经被销毁了.我怎样才能完成这项工作?
更新:
我在片段而不是对话框上尝试了相同的逻辑,结果相同,这似乎与 addOnCompleteListener
中的 firestoreService.doesUserAlreadyExists
有关,因为一个异步回调在另一个异步回调中。如何解决这个问题?
问题是没有要检查的“用户”集合,因为我删除了“用户”集合,所以 addOnSuccessListener
或 addOnFailureListener
都没有被调用。
我希望在集合不存在时抛出异常。
最好使用 addOnCompleteListener
而不是 addOnSuccessListener
侦听器,因为它保证无论如何都会被触发
例如:
db.collection(USER_COLLECTION)
.whereEqualTo("email", email).get()
.addOnCompleteListener { task ->
if(task.isSuccessful){
for (document in task.result) {
if (document.exists()) {
//..
}
}
}
else{
//..
}
}