0

I want to show username at my database, but database written null. I think because my variable don't get declaration in DataSnapshot. this is my script

private fun saveDataToFireBase() {

    var currentName : String? = null

    useRef.child(mAuth).addValueEventListener(object : ValueEventListener{
        override fun onDataChange(p0: DataSnapshot) {
            if (p0.exists()){
                currentName = p0.child("username").getValue().toString()
            }
        }

        override fun onCancelled(p0: DatabaseError) {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }
    })

    val uuid = UUID.randomUUID().toString()
    val messageText = edt_input.text.toString()

    val ref = FirebaseDatabase.getInstance().getReference("message-group/$uuid")
    val data = ChatModel ( uuid, currentName.toString(), messageText , mAuth, ""  )
    ref.setValue(data)
}

enter image description here

If in java we make variable before onCreate then:

private fun saveDataToFireBase() {

    useRef.child(mAuth).addValueEventListener(new ValueEventListener() {
        @Override
            public void onDataChange(DataSnapshot dataSnapshot)
            {
                if (dataSnapshot.exists())
                {
                    currentUserName = dataSnapshot.child("name").getValue().toString();
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

0

Data is loaded from Firebase asynchronously, since it may take some time. Instead of blocking the code while the data is retrieved (which would also block the user from using the app), the main code continues while the data is being loaded. And then when the data is available, your onDataChange is called.

You can most easily see this with some logging:

Log.d("TAG", "Before starting to load data")
useRef.child(mAuth).addValueEventListener(object : ValueEventListener{
    override fun onDataChange(snapshot: DataSnapshot) {
        Log.d("TAG", "Got data")
    }

    override fun onCancelled(error: DatabaseError) {
        throw error.toException()
    }
})
Log.d("TAG", "After starting to load data")

When you run this code, it prints:

Before starting to load data

After starting to load data

Got data

This is probably not the order you expected, but it perfectly explains the result you're getting. By the time your val data = ChatModel ( uuid, currentName.toString(), messageText , mAuth, "" ) runs, the data hasn't been loaded yet, so currentName doesn't have a value.


The solution is to put all code that needs the data from the database inside the onDataChange method, or to call it from there.

So for example:

override fun onDataChange(snapshot: DataSnapshot) {
    val uuid = UUID.randomUUID().toString()
    val messageText = edt_input.text.toString()

    val ref = FirebaseDatabase.getInstance().getReference("message-group/$uuid")
    val data = ChatModel ( uuid, currentName.toString(), messageText , mAuth, ""  )
    ref.setValue(data)
}

Also see:

Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807