Java Can';t在内部类/循环中将元素添加到列表中

Java Can';t在内部类/循环中将元素添加到列表中,java,android,Java,Android,我想保存在“名称”列表中找到的所有文档ID。该列表创建为全局类变量。代码正在运行,documentid都被添加到列表“names”中,但一旦代码离开内部类(OnComplete),它就会再次被删除 我知道java像对待普通类一样对待内部类。但是因为它是一个重写类,所以我不能从该类返回任何内容。我怎样才能访问列表的更改 public class HomeFragment extends Fragment { List<String> names = new ArrayList

我想保存在“名称”列表中找到的所有文档ID。该列表创建为全局类变量。代码正在运行,documentid都被添加到列表“names”中,但一旦代码离开内部类(OnComplete),它就会再次被删除

我知道java像对待普通类一样对待内部类。但是因为它是一个重写类,所以我不能从该类返回任何内容。我怎样才能访问列表的更改

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
                        }

                    }
                });
    }
}
公共类HomeFragment扩展了片段{
列表名称=新的ArrayList();
@可空
@凌驾
创建视图时的公共视图(@NonNull LayoutInflater inflater、@Nullable ViewGroup container、@Nullable Bundle savedInstanceState){
返回充气机。充气(R.layout.fragment_home,空);
}
@凌驾
已创建视图上的公共void(视图,@Nullable Bundle savedInstanceState){
加法();
}
公共无效补遗(){
db.collection(“Recipes”).get()
.addOnCompleteListener(新的OnCompleteListener(){
@凌驾
未完成的公共void(@NonNull任务){
if(task.issusccessful()){
对于(QueryDocumentSnapshot文档:task.getResult()){
name.add(document.getId());
}
}否则
{
//日志
}
}
});
}
}

Firebase数据库调用是异步的。从
OnCompleteListener
(匿名内部类)中编辑类变量是可以的,但是您必须了解
onComplete
中的代码不会立即执行

调用
db.collection(…).get().addOnCompleteListener(…)
接受匿名侦听器类并启动后台进程以获取数据(在不同的线程上)。该函数立即返回。后台进程提取完数据后,会对您提供的侦听器调用
onComplete
方法(数百到数千毫秒后)

例如,如果您添加如下所述的检查,它将首先从names size=0的addElements打印问候语,然后从names size>0的onComplete打印问候语(假设查询返回数据)。在这之后,您可以在任何需要的地方使用
名称
(只要片段没有被破坏,值就会留在那里),但是您的代码必须设置为能够等待这一情况发生

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());
}
public void addElements(){
//这是第一名
System.out.println(“起始加法器”);
db.collection(“Recipes”).get()
.addOnCompleteListener(新的OnCompleteListener(){
@凌驾
未完成的公共void(@NonNull任务){
if(task.issusccessful()){
对于(QueryDocumentSnapshot文档:task.getResult()){
name.add(document.getId());
}
}否则
{
//日志
}
//这将在将来数据库调用完成时运行
System.out.println(“来自ONCOMPLETE的你好”);
printNamesSize();
//如果在UI元素中显示“名称”,则
//很可能需要调用一个方法来更新
//这里的UI元素,一旦得到名称
}
});
//这将运行第二次,但此处的名称将为空(尚未运行onComplete)
System.out.println(“来自加法器的你好”);
printNamesSize();
//如果您的代码在调用addelement后立即尝试使用名称
//它仍然为空,尚未完成数据库调用
}
void printNamesSize(){
System.out.println(“names size=“+names.size());
}

尝试使用接口类。创建一个具有数组列表变量的新接口类。看起来您正在调用Firebase以获取一些数据,这是异步的。您在哪里检查“名称”是否有任何条目?(示例代码中的一些带注释的日志输出会使问题更清楚-例如,这里它显示“names”有条目,而这里它显示为空)我删除了检查它是否有条目,以使StackOverflow的代码更简单,但我有一个检查并找到了文档ID,但我不知道如何将它们从内部类传递到类,因为我不能做任何参考资料,也不能给班级做任何其他的东西,所以我检查了一下。数据库返回元素。我真的检查过了。此外,即使我只是向全局创建的字符串添加一个随机字符串值,该字符串在我离开类时也会被清除。我知道问题在于bc Java将内部类视为真正的类,但由于它是一个重写类,所以我无法传递任何值。我检查了以下内容:-就在names.add之后,数据在列表中并且可以显示-在for循环之后,我再次检查,如果数据仍然在列表中。它是——在If/else之后。所有数据仍在列表中-在db.collection之后。它不再在列表中了-我还用一个全局字符串检查了当我修改这个字符串时会发生什么。与列表相同。