问题
I have some data at a certain reference in Firebase and I'm retrieving it using addChildEventListener() and putting it in a HashMap<String, Object> like this:
final HashMap<String, Object> map1 = new HashMap<>();
ref.child(requestID).child(key).addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot.getValue() != null) {
map1.put(dataSnapshot.getKey(), dataSnapshot.getValue());
Log.d("map1", map1.toString());
} else {
}
}
...
...
});
The problem is that the data is getting added one-by-one and Log.d is printing out:
D/map1: {key=value}
D/map1: {key=value, key=value}
D/map1: {key=value, key=value, key=value}
D/map1: {key=value, key=value, key=value, key=value}
D/map1: {key=value, key=value, key=value, key=value, key=value}
What I want is to put this data into map1 all at once and get this
D/map1: {key=value, key=value, key=value, key=value, key=value} printed out.
I want to use addChildEventListener() only as I want to run the piece of code only when onChildAdded() and not every time onDataChange().
Please help me figure this out.
回答1:
A ChildEventListener is triggered for each individual child. That is a great interface if you're doing something like updating the user interface, because you can know exactly what to do: onChildAdded -> add UI element, onChildChanged -> update UI element, etc.
If you want to get all matching elements in one go, you should use a ValueEventListener:
ref.child(requestID).child(key).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
HashMap<String, Object> map1 = new HashMap<>();
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
map1.put(childSnapshot.getKey(), childSnapshot.getValue());
}
Log.d("map1", map1.toString());
}
回答2:
I don't think there is a very clean solution to exactly what you are trying to achieve. You want to get all the data at once instead of one by one, but what happens when you get a new child? You will get it one by one.
You could do something like this which would theoretically give you the entire hashmap at once, but for any subsequent children added, they too will be added one by one. You will have to use ValueEventListener, only once however, and move your old code inside it's onDataChange.
reference.child(requestID).child(key).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
long startChildCount = dataSnapshot.exists() ? dataSnapshot.getChildrenCount() : 0;
int i = 0;
HashMap<String, Object> map1 = new HashMap<>();
ArrayList<DataSnapshot> tempSnapshots = new ArrayList<>();
reference.child(requestID).child(key).addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
i++;
if (i < childCount) {
tempSnapshots.add(dataSnapshot);
} else if (i == childCount) {
for (DataSnapshot snapshot : tempSnapshots) {
map1.put(snapshot.getKey(), snapshot.getValue());
}
} else {
map1.put(dataSnapshot.getKey(), dataSnapshot.getValue());
}
}
});
}
});
来源:https://stackoverflow.com/questions/42469250/how-to-add-all-data-at-once-in-a-hashmap-under-addchildeventlistener-of-fireba