2

suppose i am getting data from firebase as

    DatabaseReference mdb=FirebaseDatabase.getInstance().getReference("users/"+id);
        mdb.addValueEventListener(new ValueEventListener() {

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                String name=dataSnapshot.child("name").getValue();
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }

        });

//point b

its working perfectly.... if i try to print that string name using

@Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                String name=dataSnapshot.child("name").getValue();
                System.out.println(name);
            }

it will print that string. but what if i want that string name outside the listener, like in first code where i have added a comment //point b

i tried defining string name globally. but it only prints the println which is inside onDatachange()... but it will print null at //point b...even if i defined the String name globally.

like

String name;
    DatabaseReference mdb=FirebaseDatabase.getInstance().getReference("users/"+id);
        mdb.addValueEventListener(new ValueEventListener() {

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                name=dataSnapshot.child("name").getValue();
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }

        });

//point b

edit actually its a function returning a string value like

public String getData(String id)
{
String name;
        DatabaseReference mdb=FirebaseDatabase.getInstance().getReference("users/"+id);
            mdb.addValueEventListener(new ValueEventListener() {

                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    name=dataSnapshot.child("name").getValue();
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }

            });

return name;

}
av development
  • 53
  • 1
  • 10

2 Answers2

0

Data is loaded from Firebase asynchronously, which unfortunately means that the approach you're trying won't be possible

The easiest way to see this is by simplifying your code to just some log statements:

    DatabaseReference mdb=FirebaseDatabase.getInstance().getReference("users/"+id);
    System.out.println("Before attaching listener");
    mdb.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            System.out.println("Inside onDataChange");
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            throw databaseError.toException(); // Don't ignore errors
        }

    });
    System.out.println("After attaching listener");

When you run this code it prints:

Before attaching listener

After attaching listener

Inside onDataChange

That is probably not the output you expected, but explains perfectly why you're not able to return the name from your function: by the time your return statement is executed, the data hasn't been loaded from Firebase yet.

There is no way to wait for the data to come available. Even if there was, it'd lead to your application being blocked and Android displaying the infamous "Application Not Responding" dialog.

Instead you will need to move the code that needs access to the name into the onDataChange method as you've done when printing it.

Also see:

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

You can't access the variable outside the onDataChange. So if you want to access the variable maybe for function/method you can implement the method inside the onDataChange. As the onDataChange will be the one running last. So make sure anything relating to the variable being done inside the onDataChange.

Devindran
  • 1
  • 2