我要保存在“名称”列表中找到的所有文档ID。该列表被创建为全局类变量。该代码正在运行,并且documentIds已全部添加到“名称”列表中,但是一旦代码离开内部类(OnComplete),它就会再次被删除。
我知道Java将内部类视为常规类。但是由于它是Override类,因此我无法将任何内容从该类传递回来。我如何仍然可以访问列表的更改?
public class HomeFragment extends Fragment {
List<String> names = new ArrayList<String>();
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_home, null);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
addElements();
}
public void addElements(){
db.collection("Recipes").get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (QueryDocumentSnapshot document : task.getResult()){
names.add(document.getId());
}
}else
{
//Log
}
}
});
}
}
答案 0 :(得分:1)
Firebase数据库调用是异步的。从OnCompleteListener
(匿名内部类)内部编辑类变量很好,但是您必须了解onComplete
中的代码不会立即执行。
对db.collection(...).get().addOnCompleteListener(...);
的调用采用了您的匿名侦听器类,并启动了一个后台进程来获取数据(在另一个线程上)。该函数立即返回。后台进程完成数据提取后,便会在您提供给它的侦听器上调用onComplete
方法(数百到数千毫秒之后)。
例如,如果您按如下所述添加检查,它将首先从名称为size = 0的addElements中打印问候语,然后从名称为> 0的onComplete中打印问候语(假设查询返回了数据)。在发生这种情况之后,您可以在需要的地方使用names
(只要Fragment不被破坏,这些值将保留在该位置),但是必须将代码设置为能够等待它发生。
public void addElements(){
// This runs 1st
System.out.println("Starting addElements");
db.collection("Recipes").get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (QueryDocumentSnapshot document : task.getResult()){
names.add(document.getId());
}
}else
{
//Log
}
// This runs 3rd! in the future when the database call is complete
System.out.println("HELLO FROM ONCOMPLETE");
printNamesSize();
// If you are showing "names" in a UI element, you would
// most likely need to call a method to update the
// UI element here, once it's gotten the names
}
});
// This runs 2nd, but names will be empty here (hasn't run onComplete yet)
System.out.println("HELLO FROM ADDELEMENTS");
printNamesSize();
// If your code immediately tries to use names after calling addElements
// it will still be empty, it hasn't finished the database call yet
}
void printNamesSize() {
System.out.println(" names size = " + names.size());
}