我正在尝试编写一个方法,该方法返回一个应该包含Firebase中节点的所有子节点的地图,但由于我必须使用回调,因此该方法返回一个空地图。
public Map<Date, String> getChildrenAsMap(String nodeId) {
DatabaseReference refernce= dbRoot.child("childName").child(nodeId);
final Map<Date, String> childMap = new HashMap<>();
refernce.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<Date, String> data = (Map<Date, String>) dataSnapshot.getValue();
for (Map.Entry<Date, String> entry : data.entrySet()) {
childMap .put(entry.getKey(), (String) entry.getValue());
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w("TAG", "onCancelled", databaseError.toException());
}
});
return childMap;
}
答案 0 :(得分:1)
这是因为Firebase查询是异步的,并且在您返回地图后会调用侦听器。为了简单起见:您不能创建这样的异步方法,因为ValueEventListener
已经是一个完全相同的接口。如果您希望这样的方法起作用,您需要创建一个为您处理它的类,但这不是必需的,因为您拥有 Firebase for Android 提供的所有内容:
DatabaseReference refernce= dbRoot.child("childName").child(nodeId);
deviceHistory.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Map<Date, String> childMap = new HashMap<>();
Map<Date, String> data = (Map<Date, String>) dataSnapshot.getValue();
for (Map.Entry<Date, String> entry : data.entrySet()) {
childMap.put(entry.getKey(), (String) entry.getValue());
}
// handle your childMap modifications in here, this gets executed after the value is retrieved
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w("TAG", "onCancelled", databaseError.toException());
}
});
我写了另一个类似的注释(虽然对于Swift,但这不是相关点)here。每次要使用它时,您都必须将逻辑写入ValueEventListener
。它已经是一种方法,因此您无需创建新方法。
答案 1 :(得分:0)
要解决此问题,您需要从onDataChange()
中获取数据。请参阅此post的答案。
这是由于在迭代之前调用的onDataChange()
的异步行为而发生的。