0

I want to get the whole value(0~5) from destinations

This is part of json data in realtime database

{"results" : [{
"destin_num" : 6,
"destinations" : [ "asdf", "qwwee", "zzzxcv11", "jkkk", "lkjhhg", "zxcvb" ],
"name" : "asdfasdfff",
"order" : 2,
"required_time" : "6hours"  }]}

the value I want to put in the String List , I use ChildEventListener() to add the value into List, but the value can't put into the List after finish the ChildEventListener().There will be nothing in List direction How to get the values?

List<String> direction=new ArrayList<String>();

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);

    DatabaseReference reference_contacts = FirebaseDatabase.getInstance().getReference("results").child("1").child("destinations");

   reference_contacts.addChildEventListener(new ChildEventListener() {
      @Override

      public void onChildAdded(DataSnapshot dataSnapshot, String s) {
          String data=dataSnapshot.getValue().toString();
          direction.add(data);
      }

      @Override
      public void onChildChanged(DataSnapshot dataSnapshot, String s) {

      }

      @Override
      public void onChildRemoved(DataSnapshot dataSnapshot) {

      }

      @Override
      public void onChildMoved(DataSnapshot dataSnapshot, String s) {

      }

      @Override
      public void onCancelled(DatabaseError databaseError) {

      }
      });


    for(int i=0;i<direction.size();i++){
        Log.e("Get data",direction.get(i));
    }

}
Patrick
  • 3
  • 2

1 Answers1

1

It's because data is loaded from Firebase asynchronously. Your for loop printing the values is actually run before onChildAdded ever gets called. It's easiest to see this by adding some logging:

Log.i("Firebase", "Before adding listener");
reference_contacts.addChildEventListener(new ChildEventListener() {
  @Override

  public void onChildAdded(DataSnapshot dataSnapshot, String s) {
    Log.i("Firebase", "In onChildAdded");
  }

  @Override
  public void onChildChanged(DataSnapshot dataSnapshot, String s) { }

  @Override
  public void onChildRemoved(DataSnapshot dataSnapshot) { }

  @Override
  public void onChildMoved(DataSnapshot dataSnapshot, String s) { }

  @Override
  public void onCancelled(DatabaseError databaseError) {
    throw databaseError.toException(); // don't ignore errors
  }
});
Log.i("Firebase", "After adding listener");

When you run this code it prints:

Before adding listener

After adding listener

In onChildAdded

That is probably not the order you expected. But is completely explains why the direction list is empty when you print it, the data hasn't been loaded yet, so onChildAdded has never been invoked.

The solution is typically to add the code that requires the data into the onChildAdded method:

So:

reference_contacts.addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String s) {
     String data=dataSnapshot.getValue().toString();
     direction.add(data);
     Log.i("Got data",direction);
  }

  @Override
  public void onChildChanged(DataSnapshot dataSnapshot, String s) {

  }

  @Override
  public void onChildRemoved(DataSnapshot dataSnapshot) {

  }

  @Override
  public void onChildMoved(DataSnapshot dataSnapshot, String s) {

  }

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

If you only want to show the data once everything is loaded, you can use a ValueEventListener instead:

reference_contacts.addValueEventListener(new ValueEventListener() {
  @Override

  public void onDataChange(DataSnapshot snapshot) {
    for (DataSnapshot dataSnapshot: snapshot.getChildren()) {
      String data=dataSnapshot.getValue(String.class);
      direction.add(data);
    }
    for(int i=0;i<direction.size();i++){
      Log.e("Get data",direction.get(i));
    }
  }
  @Override
  public void onCancelled(DatabaseError databaseError) {
    throw databaseError.toException(); // don't ignore errors
  }
});

Note that this is an incredibly common source of confusion for developers new to Firebase (and asynchronous APIs in general). I highly recommend studying some of the answers to some of these previous questions about the topic:

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