Akash Chaudhary
Akash Chaudhary

Reputation: 711

Function returns value before inner results are finished in Kotlin

I am using Kotlin in android to get data from firebase database. But the function return the value before inner listener returns value due to which i get null or empty value. My code is

 fun getImages(image: String): String {
    var imageUrl= ""

    val databaseReference = database.getReference(image)
    databaseReference.addValueEventListener(object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {

            imageUrl = dataSnapshot.value as String

            println(imageUrl)
            println("reached here 1")

        }

        override fun onCancelled(error: DatabaseError) {
            Log.w(TAG, "Failed to read value.", error.toException())
        }
    })
    println("reached here 2")
    return imageUrl

}

The above function prints "reached here 2" before printing "reached here 1" due to which imageUrl value is returned as empty.

Upvotes: 1

Views: 380

Answers (1)

Youssef
Youssef

Reputation: 46

You're calling an asynchronous function

databaseReference.addValueEventListener(object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {

            imageUrl = dataSnapshot.value as String

            println(imageUrl)
            println("reached here 1")

        }

        override fun onCancelled(error: DatabaseError) {
            Log.w(TAG, "Failed to read value.", error.toException())
        }
    })

this function is executed simultaneously with your function "getImages",and ends after your function. For this reason your function always returns an empty string.

I recommend you assign the value of the string inside "onDataChange (dataSnapshot: DataSnapshot)", and then call a function to use the newly assigned value.

class YourClass {

  var imageUrl= ""

  //Your image reference 
  var image= ""

  override fun onCreate(savedInstanceState: Bundle?) {

     //Call your function to get your imageUrl
     //Use callback to react firebase asynchronous function
     getImages(image, callback)
  }

  fun getImages(image: String, callback : ValueEventListener) {

    val databaseReference = database.getReference(image)
    databaseReference.addValueEventListener(callback)

  }

  //Define ValueEventListener
  val callback = object : ValueEventListener {
      override fun onDataChange(dataSnapshot: DataSnapshot) {

        //Assign value
        this.imageUrl = dataSnapshot.value as String

        //Call a function to use the value 
        this.doSomething()

      }

      override fun onCancelled(error: DatabaseError) {
        Log.w(TAG, "Failed to read value.", error.toException())
      }
  }

  fun doSomething(){

  }


}

Upvotes: 3

Related Questions