What you're seeing is likely the fact that data from Firebase is loaded asynchronously. The first time you encounter this, it's a big paradigm shift. But since most modern cloud APIs work this way, it's best to embrace it as quickly as possible.
The easiest way I've found to see what happens when we place some logging statements:
System.out.println("Before adding listener");
mRefReg.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("In onDataChange");
}
public void onCancelled(DatabaseError databaseError) { }
});
System.out.println("After adding listener");
Contrary to what your intuition tells you, the output of this will be:
Before adding listener
After adding listener
In onDataChange
The reason for this is (as I said at the start) that Firebase asynchronously gets the data from the database. A fun way to realize why that is, is to make a change to your data (for example in your Firebase Database console). When you make this change, the onDataChange
will be invoked again and print another:
In onDataChange
Unfortunately this means that you cannot do the following to handle the children count:
int count = -1;
System.out.println("Before adding listener, count="+count);
mRefReg.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
count = dataSnapshot.getChildrenCount();
System.out.println("In onDataChange, count="+count);
}
public void onCancelled(DatabaseError databaseError) { }
});
System.out.println("After adding listener, count="+count);
Because the output will be:
Before adding listener: count=-1
After adding listener: count=-1
In onDataChange: count=3 (assuming you have 3 children)
The best trick I've found to deal with this asynchronous loading is to reframe the problem. Instead of saying "first we get the count, then we do xyz with it", try framing it as "whenever we get the count, do xyz with it". This means that you need to move the code that requires the count into onDataChange()
:
mRefReg.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
int count = dataSnapshot.getChildrenCount();
// TODO: show the count in the UI
}
public void onCancelled(DatabaseError databaseError) { }
});
If you implement it like this, the count in the UI will be updated whenever the number of items in the database changes.