使用FireBase/FireStore在Java的内部函数中访问数据 [英] Accessing data within an inner function in Java with FireBase/FireStore
问题描述
我正在使用Google的FireStore后端编写一个Android应用程序.从官方文档中获取火库集合中所有文档的代码如下:
I am coding an android app using Google's FireStore backend. The code to grab all the documents in a firestore collection is as follows, from the official documentation:
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
方法的返回类型会产生错误.在这种方法中是否有访问元素的标准方法?
Where the above code outputs to Log.d(...)
, I would like to have my program add the results of the document.getData()
call to an ArrayList
accessible outside the inner class/method. I'm not sure what is the best way to do this. Attempting to change the return the return type of the onComplete
method yields errors. Is there a standard way of accessing elements in methods like this?
声明变量并尝试在类中进行变异也是不可能的,除非变量是最终变量,否则将使问题无济于事.
Declaring a variable and trying to mutate within the class also isn't possible, unless the variable is final, which defeats the point.
推荐答案
这是一个异步调用(它会启动后台进程来执行Firebase查询,完成后它将执行您的 onComplete
侦听器),因此您不能期望在进行数据库调用后立即拥有数据.例如,如果您的函数看起来像
That is an asynchronous call (it launches a background process to do the Firebase query, and once that is done it executes your onComplete
listener), so you can't expect to have the data in hand immediately after making the database call. For example, if your function looks like
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
侦听器填充的类成员(然后,您必须构造程序以处理随机输入的数据).
You need to structure your program so that it can wait for the data to arrive. There are a couple ways you could do this. One would be to have list
be a class member that gets filled by the onComplete
listener (then you have to structure the program to handle data coming in at random times).
另一种方法是拥有一个数据处理程序例程,该例程接受 ArrayList
并对其进行处理.获取所有数据后,可以从 onComplete
侦听器调用此方法.例如:
Another way would be to have a data handler routine that takes the ArrayList
and does something with it. This method could be called from the onComplete
listener once you've gotten all the data. For example:
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
}
这篇关于使用FireBase/FireStore在Java的内部函数中访问数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!