public List<String> getContactsFromFirebase(){
FirebaseDatabase.getInstance().getReference().child("Users")
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Users user = snapshot.getValue(Users.class);
assert user != null;
String contact_found = user.getPhone_number();
mContactsFromFirebase.add(contact_found);
Log.i("Test", mContactsFromFirebase.toString());
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
return mContactsFromFirebase;
}
我似乎找不到错误。在上面的代码中,当我调用日志时,我从 mContactsFromFirebase
,但是 getContactsFromFirebase()
方法返回空列表。你能帮帮我吗?
1条答案
按热度按时间roqulrg31#
从firebase异步加载数据。因为从服务器获取数据可能需要一些时间,所以主要的android代码会继续,firebase会调用您的
onDataChange
当数据可用时。这意味着当你
return mContactsFromFirebase
它还是空的。最简单的方法是放置一些日志语句:运行此代码时,它将打印:
在附加侦听器之前
附加侦听器后
在ondatachange中
这可能不是您期望的输出顺序。正如您可以看到的,在调用回调之前
onDataChange
. 这就解释了为什么您返回的列表是空的,或者(更准确地说)当您返回它时它是空的,并且只在以后被填充。有几种方法可以处理这种异步加载。
最简单的解释是将所有返回列表的代码放入
onDataChange
方法。这意味着此代码仅在加载数据后执行。以最简单的形式:但是还有更多的方法,包括使用自定义回调(类似于firebase自己的回调)
ValueEventListener
):java 语:
Kotlin:
现在可以将此接口的实现传递给
getContactsFromFirebase
方法:java 语:
Kotlin:
然后这样称呼:
java 语:
Kotlin:
它不像同步加载数据那么简单,但它的优点是运行时不会阻塞主线程。
这个主题以前讨论过很多,所以我建议你也来看看这些问题:
这篇来自道格的博文
在firebase侦听器中设置singleton属性值(在这里我解释了在某些情况下如何获得同步数据加载,但通常不能)
返回一个对象android(我第一次使用log语句解释发生了什么)
是否可以从firebase同步加载数据?
https://stackoverflow.com/a/38188683 (道格展示了一种很酷但很复杂的使用
Task
带firebase数据库的api)如何作为方法的结果返回datasnapshot值(从那里我借用了一些回调语法)