我正在使用Google的FireStore后端编写一个Android应用程序。从官方文档中获取Firestore集合中所有文档的代码如下:
db.collection("cities")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Log.d(TAG, document.getId() + " => " + document.getData());
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
以上代码输出到Log.d(...)
的地方,我想让我的程序将document.getData()
调用的结果添加到内部类/方法外部可访问的ArrayList
上。我不确定执行此操作的最佳方法是什么。尝试更改return onComplete
方法的返回类型会产生错误。在这种方法中是否有访问元素的标准方法?
声明变量并尝试在类中进行变异也是不可能的,除非该变量是最终变量,否则将使问题无济于事。
答案 0 :(得分:1)
我想让我的程序将document.getData()调用的结果添加到内部类/方法外部可访问的ArrayList中。
在这种情况下,如果您使用的是模型类,则应使用toObject()
方法,并在YourModelClass
中添加ArrayList
类型的对象,如下所示:
if (task.isSuccessful()) {
List<YourModelClass> list = new ArrayList<>();
for (QueryDocumentSnapshot document : task.getResult()) {
YourModelClass yourModelClass = document.toObject(YourModelClass.class);
list.add(yourModelClass);
//Do what you need to do with your list
}
}
如您所见,我建议您在回调中使用YourModelClass
对象的列表。这是因为onComplete()
方法具有异步行为,您不能简单地在回调之外使用该列表,因为它始终为空。
尝试更改return的onComplete方法的返回类型会产生错误。
更改方法的返回类型不会给您带来错误,但是结果始终是一个空列表。您现在无法返回尚未加载的内容。快速解决此问题的方法是,仅在onComplete()
方法内部使用该对象列表,就像我上面已经写过的那样;或者,如果您想在外部使用它,我建议您从在 post 中,我已经说明了如何使用自定义回调来完成此操作。您也可以查看此 video 以获得更好的理解。
答案 1 :(得分:1)
这是一个异步调用(它会启动一个后台进程来执行Firebase查询,一旦完成,它就会执行您的onComplete
侦听器),因此您不能期望在此之后立即拥有数据进行数据库调用。例如,如果您的函数看起来像
void getData() {
final List<MyData> list = new ArrayList<>();
db.collection("cities")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Log.d(TAG, document.getId() + " => " + document.getData());
list.add(new MyData(document.getData()));
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
Log.d(TAG, "List size = " + list.size()); // will print 0
// list will be empty here, the firebase call will take hundreds
// to thousands of milliseconds to complete
}
您需要对程序进行结构设计,使其可以等待数据到达。您可以通过几种方法来执行此操作。一种方法是让list
成为由onComplete
侦听器填充的类成员(然后,您必须构造程序以处理随机时间传入的数据)。
另一种方法是让数据处理程序例程使用ArrayList
并对其执行某些操作。获取所有数据后,可以从onComplete
侦听器调用此方法。例如:
void getData() {
db.collection("cities")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<MyData> list = new ArrayList<>();
for (QueryDocumentSnapshot document : task.getResult()) {
Log.d(TAG, document.getId() + " => " + document.getData());
list.add(new MyData(document.getData()));
}
processData(list);
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
}
void processData(List<MyData> data) {
// do stuff with the data, or make a copy, or otherwise share it
// with the rest of your program
}