Reputation: 1551
I am implementing firebase in my app. Please refer the below image as a reference to my database.
I have an array of SLC names and I need to generate an arrayList of SLC keys. So I am trying to create an arrayList of specific SLC keys. Please see the below code once.
for (int i = 0; i < arr.size(); i++)
{
Query query = ref.child(pref.getString("groupSelectedDCU", "") + "/" + "DeviceList")
.orderByChild("name")
.equalTo(arr.get(i));
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren())
{
Log.d("arrID", child.getKey() + "");
arrID.add(child.getKey());
}
Log.d("arrID", Arrays.toString(arrID.toArray()));
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
Log.d("arrID", Arrays.toString(arrID.toArray()));
Here I am trying to add all the SLC keys into the arrID
arraylist. But while accessing the arrayList, it returns an empty array. Am I missing something or do I have to add any more listeners? Need your help.
Upvotes: 0
Views: 1566
Reputation: 19339
You misunderstood how addListenerForSingleValueEvent
works. The provided ValueEventListener
methods will be called asynchronously in the background, when the query response finally arrives from the network. As such, when this last statement runs (after the for loop):
...
Log.d("arrID", Arrays.toString(arrID.toArray()));
the arrID
will still be empty since none of the onDataChange
methods has been called yet.
Alternative solution. If you need to wait until all queries are done, try this instead:
List<String> arrID = ArrayList<String>();
int remainingQueries = arr.size();
for (int i = 0; i < arr.size(); i++) {
Query query = ...
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
Log.d("arrID", child.getKey() + "");
arrID.add(child.getKey());
}
Log.d("arrID", Arrays.toString(arrID.toArray()));
if (--remainingQueries == 0) onQueriesDone(arrID);
}
@Override
public void onCancelled(FirebaseError firebaseError) { }
});
}
which will call this method when done:
private void onQueriesDone(List<String> arrID) {
Log.d("arrID", Arrays.toString(arrID.toArray()));
}
In particular, we don't need synchronization locks to access the shared counter remainingQueries
since all Firebase callbacks are triggered on the main thread.
Upvotes: 2