Firebase data reading always returns null

1

I'm trying to read data from users that are stored in Firebase through an Android application. I'm always having null in TextViews, but I see the value in the Logcat of Android Studio.

I have already checked my security rules and they allow you to read data.

This is my class that connects to 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 it like this:

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

The method for creating a new User works. Only methods to read data are returned null. Is there something different happening in ValueEventListener ?

    
asked by anonymous 24.02.2018 / 22:41

1 answer

2

The reason for creating User to run (and not read) is:

Firebase read data asynchronously.

This means that the reading of data is passed to another Thread (I'll call it a Secondary Thread) that waits 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 you read data synchronously, it would be running on the Main Thread. This is the same thread responsible for drawing the elements of your application on the user's screen. It is also the Thread that performs several other operations of your application.

Reading on 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 displayed on the screen until the data is read. And if an error occurs in reading data, or if the data is taking a long time to read, your application will not perform any further operation because the Main Thread has been locked.

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 ready, the microwave warns us (through a sound) that we can go there and get it.

No one stands in front of the microwave waiting for the food to finish warming up (as in synchronous reading). That's because the microwave does not require any human interaction to work. So you can go do other things while the food is being heated. Pretty efficient, is not it?

Correcting the problem in your code

Now that all the explanation has been given, let's fix the code.

I do not recommend creating another class for reading / writing Firebase data. Perform all of these operations on your MainActivity.

So after putting your code in MainActivity, you can use the result you got from reading data within your onDataChange() method:

        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) {}
                });
    
24.02.2018 / 22:41