Firebase data reading always returns null

Asked

Viewed 585 times

2

I’m trying to read data from users who are saved in Firebase, through an Android application. I’m always having null in Textviews, but I see the value in Android Studio’s Logcat.

I’ve checked my security rules and they allow data reading.

This is my class connecting with Firebase:

public class FirebaseBD {
    private DatabaseReference ref;
    private Usuario usuario = null;
    private List<Usuario> listaUsuarios = null;

    public FirebaseBD(){
        ref = FirebaseDatabase.getInstance().getReference();
    }

    public void novoUsuario(Usuario usuario){
        ref.child("usuarios").push().setValue(usuario);
    }

    public Usuario lerUsuarioPorId(String idUsuario){
        ref.child("usuarios").child(idUsuario)
                .addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        usuario = dataSnapshot.getValue(Usuario.class);
                        Log.i(this.getClass().getSimpleName(),
                                usuario.toString());
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {}
                });
        return usuario;
    }

    public List<Usuario> lerUsuarios(){
        ref.child("usuarios")
                .addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        listaUsuarios = new ArrayList<>();
                        for(DataSnapshot snapshot : dataSnapshot.getChildren())
                        {
                            listaUsuarios.add(snapshot.getValue(Usuario.class));
                        }
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {}
                });
        return listaUsuarios;
    }

}

And in my mainactivity I’m calling her so:

Usuario usuario = new FirebaseBD().lerUsuarioPorId("usuarioTeste");
txtNome.setText(usuario.getNome());
txtEmail.setText(usuario.getEmail());

The method for creating a new User works. Only the methods for reading data return null. Something different is happening in the ValueEventListener?

1 answer

3


The reason the method of creating User works (and read not) is:

Firebase reads data asynchronously.

This means that the data reading is passed to another Thread (I will call it Secondary Thread) which is waiting for the result and only returns when it is ready (that is, when the data has been read).

But what is the difference between asynchronous and synchronous?

If the data reading were done synchronously, it would be running in the Main Thread. This is the same Thread responsible for drawing the elements of your application on the user screen. It’s also Thread that performs several other operations of your application.

The reading happening in the Main Thread implies that this Thread is waiting for the data to be read to continue its execution. Therefore, your application will not be shown on the screen until the data is read. And if an error occurs in reading data, or if the data is taking too long to read, your application will not perform any more operation as the Main Thread has been blocked.

We can imagine this as putting the food to heat in the microwave. We just put it there and let it warm up. When it is already ready, the microwave warns us (through a sound) that we can already go there to get it.

No one is left standing in the microwave waiting for the food to finish heating (as in the synchronous reading). That’s because the microwave doesn’t require any human interaction to work. So you can go do other things while the food is being heated. Very efficient, it’s not?

Fixing the issue in your code

Now that all the explanation has been given, we will correct the code.

I do not recommend create another class for reading/writing Firebase data. Perform all these operations on your Mainactivity.

So after you put your code into Mainactivity, you can use the result you got from reading data within your method onDataChange():

        DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
        ref.child("usuarios").child("usuarioTeste")
                .addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        Usuario usuario = dataSnapshot.getValue(Usuario.class);
                        txtNome.setText(usuario.getNome());
                        txtEmail.setText(usuario.getEmail());
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {}
                });

Browser other questions tagged

You are not signed in. Login or sign up in order to post.