Home > Blockchain >  How to use "Async & Await" here
How to use "Async & Await" here

Time:11-08

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.

  • Related