Irshaad
Irshaad

Reputation: 3

Cannot call Kotlin variable value which declared by function

I am declaring a global variable called basic_id inside class.

class userOverview : AppCompatActivity() {
   private lateinit var database: FirebaseDatabase
   private var basic_id : String = "00"

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.user_overview)
       database = FirebaseDatabase.getInstance()

       loadBasicDetails() //this function will assign basic_id a non-zero value

       //Display Toast of current value of basic_id
       Toast.makeText(this, "On loading - "+basic_id, Toast.LENGTH_SHORT).show()

       button.setOnClickListener() {
          Toast.makeText(this, "Button clicked - "+basic_id, Toast.LENGTH_SHORT).show()
       }
   }

   private fun loadBasicDetails() {
        val q : Query =  database.getReference("basic").orderByChild("epf_no").equalTo("12345")
            q.addValueEventListener(object : ValueEventListener {
                override fun onDataChange(data: DataSnapshot) {
                    for (dataChild in data.children) {
                        val basicDetails = dataChild.getValue(basicDetailsModel::class.java)
                        basic_id = basicDetails!!.basic_id
                    }
                }
                override fun onCancelled(error: DatabaseError) {error.toException()}
            })
    }
}

I am assigning database values to custom object (basicDetailsModel::class.java) and assign it's value to global variable basic_id (Its works fine)
When activity starts, it shows a toast "On loading - 00"
But when clicking button, it shows a toast "Button clicked - 06"

Why its not working on Toast "On loading - 06"

Upvotes: 0

Views: 244

Answers (2)

Animesh Sahu
Animesh Sahu

Reputation: 8096

ValueEventListener doesn't run as soon as you've registered it, it will be triggered after the network request has been finished, you may wanted to use coroutines, but a simple and ideal solution for your case would be to use a callback here.

override fun onCreate(savedInstanceState: Bundle?) {
    //...
    loadBasicDetails { // will be triggered after variable is set :)
        Toast.makeText(this, "On loading - "+basic_id, Toast.LENGTH_SHORT).show()
    }       
    //...
}

private inline fun loadBasicDetails(crossinline callback: () -> Unit) {
    database.getReference("basic").orderByChild("epf_no").equalTo("12345")
        .addValueEventListener(object : ValueEventListener {
            override fun onDataChange(data: DataSnapshot) {
                //... set the variable
                callback()
            }
            override fun onCancelled(error: DatabaseError) {error.toException()}
        })
}

Upvotes: 1

Sergio
Sergio

Reputation: 30655

When "On loading -..." Toast is shown basic_id variable does not have time to change, bcz you are making an asynchronous network request, which may execute some time depending on internet connection. So Toast "On loading -..." will be shown before basic_id variable is changed.

Upvotes: 0

Related Questions