I want to await the other processes until "Getting Username from firestore and putting it into postMap" How can I make them wait? Because if they don't wait username can not uploading to firestore and that cause some problems. I know I can use "Async & Await" method but how? (You can look at the comment lines that I created and see which processes are happening there.)
if(selectedPicture != null){
imageReference.putFile(selectedPicture!!).addOnSuccessListener {
val uploadPictureReference = storage.reference.child("images").child(imageName)
uploadPictureReference.downloadUrl.addOnSuccessListener {
val downloadUrl = it.toString()
if(auth.currentUser != null){
val postMap = hashMapOf<String,Any>()
postMap.put("downloadUrl",downloadUrl)
postMap.put("userEmail",auth.currentUser!!.email!!)
postMap.put("comment",binding.uploadCommentText.text.toString())
postMap.put("date",Timestamp.now())
//Get Username from firestore and put it into postMap
db.collection("UserDetails").addSnapshotListener { value, error ->
if(error!=null){
Toast.makeText(this,error.localizedMessage,Toast.LENGTH_LONG).show()
}else{
if(value!=null){
if(!value.isEmpty){
val documents = value.documents
for (document in documents){
val username = document.get("username")as String
//Put username into postMap
postMap.put("username",username) as String
}
}
}
}
}
//upload postmap to firestore
firestore.collection("Posts").add(postMap).addOnSuccessListener {
finish()
}.addOnFailureListener{
Toast.makeText(this,it.localizedMessage,Toast.LENGTH_LONG).show()
}
}
}
}.addOnFailureListener{
Toast.makeText(this,it.localizedMessage,Toast.LENGTH_LONG).show()
}
}
CodePudding user response:
I don't know 100 % what you are trying to achieve, but by adding the firebase-ktx library, you can use .await()
to get your values inside a coroutine.
// Returns true when everything was successful, or false if not
suspend fun getUserNameAndPutInPostMap(selectedPicture: File?): Boolean {
try {
if (selectedPicture == null || auth.currentUser == null) return
imageReference.putFile(selectedPicture!!).await()
val downloadUrl = storage.reference.child("images").child(imageName).downloadUrl.await().toString()
val userName = db.collection("UserDetails").get("username").await().toString()
val postMap = hashMapOf<String,Any>().apply {
put("downloadUrl", downloadUrl)
put("userEmail", auth.currentUser!!.email!!)
put("comment",binding.uploadCommentText.text.toString())
put("date",Timestamp.now())
put("username",username)
}
firestore.collection("Posts").add(postMap).await()
} catch (e: Exception) {
return false
}
}
CodePudding user response:
The call to firestore.collection("Posts").add(postMap)
will need to be inside the addSnapshotListener
callback, right after you populate the postMap
with postMap.put("username",username) as String
.
db.collection("UserDetails").addSnapshotListener { value, error ->
if(error!=null){
Toast.makeText(this,error.localizedMessage,Toast.LENGTH_LONG).show()
}else{
if(value!=null){
if(!value.isEmpty){
val documents = value.documents
for (document in documents){
val username = document.get("username")as String
//Put username into postMap
postMap.put("username",username) as String
//upload postmap to firestore
firestore.collection("Posts").add(postMap).addOnSuccessListener {
finish()
}.addOnFailureListener{
Toast.makeText(this,it.localizedMessage,Toast.LENGTH_LONG).show()
}
}
}
}
}
}
I also recommend converting the onSnapshot
to a get().addOnCompleteListener(
call, because I'm pretty sure only mean to read the user data once.