0

I am trying to read a node in my database and return the value retrieved in a single method. When i run the code the data is logged on the console but the method returns a null value.

What i Know:

I know that Firebase retrieves/synchronizes with the database automatically in the background therefore the code inside onDataChanged is executed last.

What i don't know:

How to get my method to return the value gotten from the onDataChanged method.

My code:

public static String telephone;
public static String getMyNumber(){
    final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
    DatabaseReference r = FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()).child("phone");
    r.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            telephone = dataSnapshot.getValue(String.class);
            Log.d("YourTag", telephone);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
    return telephone;
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
T double
  • 349
  • 3
  • 12
  • Your `getMyNumber` method runs synchronously on the main thread. The data is retrieved from the Firebase Database asynchronously on a separate thread. If you're targeting regular Java/JVM, you can use semaphores to synchronize the two. On Android this is not possible. See my answer here: http://stackoverflow.com/questions/33203379/setting-singleton-property-value-in-firebase-listener/33204705#33204705 – Frank van Puffelen Nov 28 '16 at 15:46
  • ok thanks for the comment. i am working on Android. – T double Nov 28 '16 at 20:41
  • In that case you have no other option then embracing the asynchronous nature of Firebase (and most modern cloud services). – Frank van Puffelen Nov 28 '16 at 21:15

2 Answers2

0

Welcome to asynchronous programming. When you attach the listener by calling addValueEventListener, your app don't automatically get the value (or the onDataChange doesn't get called directly.

If you are about to update the UI after the telephone is retrieved, then put the code inside the onDataChange method.

Hope this helps :)

Wilik
  • 7,630
  • 3
  • 29
  • 35
0

To get the value you should use Callbacks:

Ex.:

private InterfaceListener mListenerForResult;

public Contructor(InterfaceListener listener) {
    this.mListenerForResult = listener;
}


public static String telephone;
public static String getMyNumber(){

final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference r = FirebaseDatabase.getInstance().getReference().child("users").child(user.getUid()).child("phone");
    r.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            telephone = dataSnapshot.getValue(String.class);
            Log.d("YourTag", telephone);
            mListenerForResult.obtainValue(telephone);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
    return telephone;
}

interface InterfaceListener {
    obtainValue(String telephone);
}

From the other class:

You should implement this inferface, and pass through the constructors.