数据从 Firebase 异步加载和同步。
如果添加一些适当的日志语句,最容易看出导致问题的原因:
public ArrayList<UserDatabase> getFriendList() {
mDatabase = FirebaseDatabase.getInstance().getReference().child("users");
final ArrayList<UserDatabase> list = new ArrayList<>();
System.out.println("Attaching listener");
mDatabase.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
System.out.println("Got data");
}
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
public void onChildRemoved(DataSnapshot dataSnapshot) {}
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
public void onCancelled(DatabaseError databaseError) {}
});
System.out.println("Returning list");
return list;
}
输出将按以下顺序打印:
附加监听器
返回列表
Got data
这可能不是您期望的顺序。但它确实解释了为什么如果按原样运行代码,列表为空。
原因是 Firebase 异步加载和同步数据。与大多数现代 Web API 一样,它不会等待结果返回(这会导致可怕的用户体验),而是让程序继续并在获取(新)数据时回调到您的代码。
处理这种行为的方法是将程序流程从“首先获取好友列表,然后对其执行 xyz”重新构建为“每当好友列表发生变化时,对其执行 xyz”。
例如,假设您只想打印有多少朋友。您当前的方法可能是:
ArrayList<UserDatabase> friends = getFriendList();
System.out.println("There are "+friends.size()+" friends");
对于 Firebase,处理此问题的一种方法是移动操作into getFriendList()
:
public void getFriendList() {
mDatabase = FirebaseDatabase.getInstance().getReference().child("users");
final ArrayList<UserDatabase> list = new ArrayList<>();
mDatabase.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
UserDatabase userDatabase = dataSnapshot.getValue(UserDatabase.class);
list.add(userDatabase);
System.out.println("There are "+friends.size()+" friends");
}
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
public void onChildRemoved(DataSnapshot dataSnapshot) {}
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
public void onCancelled(DatabaseError databaseError) {}
});
}