0

I'm trying to get an information ('firstDate') saved in firebase using this code:

if(currentUser != null){
    val ref = FirebaseDatabase.getInstance().getReference("Users").child(FirebaseAuth.getInstance().currentUser!!.uid)

    val menuListener = object : ValueEventListener {
        override fun onCancelled(databaseError: DatabaseError) {
            // handle error
        }
        @SuppressLint("SetTextI18n", "LongLogTag")
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            user = dataSnapshot.getValue(User::class.java)
            Log.i("************************* before Assignement", myFirstDay)
            myFirstDay = user?.firstDate
            Log.i("************************* after Assignement", myFirstDay)
        }
    }
    ref.addValueEventListener(menuListener)
}
getFirstDayReg()

Log.i("************************* myFirstDayReg", myFirstDay)

The problem: anything before ref.addValueEventListener(menuListener) returns the correct answer but this one :

    Log.i("************************* myFirstDayReg", myFirstDay)

It does not giving me anything (no return / nothing at all )

Please help to get the value user?.firstDate and assigned in myFirstDay because I need to use it later on my code.

According to Mr. Alex answer i made this code but i still have the same problem nothing changed

interface MyCallback {
    fun onCallback(value: String)
}
fun readData(myCallback: MyCallback){
        if(currentUser != null){
            val ref = FirebaseDatabase.getInstance().getReference("Users").child(FirebaseAuth.getInstance().currentUser!!.uid)

        val menuListener = object : ValueEventListener {
            override fun onCancelled(databaseError: DatabaseError) {
                // handle error
            }
            @SuppressLint("SetTextI18n", "LongLogTag")
            override fun onDataChange(dataSnapshot: DataSnapshot) {
                user = dataSnapshot.getValue(User::class.java)
                Log.i("************************* before Assignement", user?.firstDate!!)
                myFirstDay = user?.firstDate!!
                myCallback.onCallback(user?.firstDate!!)

            }
        }
        ref.addListenerForSingleValueEvent(menuListener)
    }
}

readData(object: MyCallback {
    override fun onCallback(value: String) {
        Log.d("TAGTAGTAGTAGTAGTAGTAG", user?.firstDate)
    }
})
WIKOSO
  • 105
  • 1
  • 2
  • 12
  • look at my answer here, please consider giving it an upvote if it ends up helping you out : https://stackoverflow.com/questions/57330766/how-to-get-data-from-any-asynchronous-operation-in-android/57330767#57330767 – a_local_nobody Aug 02 '19 at 18:47

2 Answers2

1

The following line of code does not giving your anything because it is placed outside the callback:

Log.i("************************* myFirstDayReg", myFirstDay)

By the time this line is called, the data isn't finished loaded from the database. Remember, Firebase APIs are asynchronous, meaning that onDataChange() method returns immediately after it's invoked, but the result that you get from the database comes some time later. There are no guarantees about how long it will take. So it may take from a few hundred milliseconds to a few seconds before the data is available. Because that method returns immediately, the value of your myFirstDay variable you're trying to use it outside the onDataChange() method, will not have been populated from the callback yet.

Basically, you're trying to use the value of myFirstDay synchronously from an API that's asynchronous. That's not a good idea. You should handle the APIs asynchronously as intended.

A quick solve for this problem would be to use myFirstDay only inside the callback, otherwise I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Thank you very much for those awesome informations, can you please form a code in kotlin for me to solve this problem ? i tried yours but i think i did not understand it well please help me – WIKOSO Jul 31 '19 at 15:21
  • 1
    I cannot code for you. You should make your own attempt given the information in the answer and ask another question if something else comes up. I can give you another example in [Kotlin](https://stackoverflow.com/questions/51594772/how-to-return-a-list-from-firestore-database-as-a-result-of-a-function-in-kotlin/51595202). It is for Cloud Firestore but same rules apply to Firebase realtime database. – Alex Mamo Jul 31 '19 at 15:25
  • i will not approve you answer till you an explanation code like you did with the others, i want that the solution will have a good effective for all future users – WIKOSO Jul 31 '19 at 15:45
  • 2
    Stack Overflow it's **not** a code writing service. As I already said, you should make your own attempt to solve this. As I invest some time and effort to write you an answer you should also take some time to solve your own problem. And if you'll think that my answer helped you, you can accept it. – Alex Mamo Jul 31 '19 at 15:51
  • i'm sorry, i don't want to be rude with you...i tried your code but i still have the same problem i can't use the returned from readData() outer...i want to use it an if expression but out of the readData fun..i will add the code to my question as i understood from you – WIKOSO Jul 31 '19 at 17:24
  • check it now please! – WIKOSO Jul 31 '19 at 17:29
  • There is no way you can use it outside. Everything should be read inside. – Alex Mamo Jul 31 '19 at 21:53
-1

According to what my friend Alex says, i made my code inside a handler for just 5 seconds and now everything is working fine:

Handler().postDelayed({
   // Your Code
 },5000)
WIKOSO
  • 105
  • 1
  • 2
  • 12
  • This is **not** how you deal with asynchronous programming. I don't recommend this solution to future visitors at all. What will you do if the operation for getting data will take more than 5 seconds? – Alex Mamo Aug 04 '19 at 09:00