等待直到检索到Firestore数据以启动活动

Rub*_*uez 5 java android firebase google-cloud-firestore

我列出了从我的Cloud Firestore数据库获取值的POJO对象列表。这个列表本身就是一个类,每当我创建一个新的列表时都会记住要检索属性。事实是,列表不是在创建活动中填写的,而是之后的时间。我尝试添加循环,任务,等待,但未获得所需的结果。这是我令人满意地检索数据的方式:

private void retrieveData(){
        reference = firestore.collection("attractions");
        reference.addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots,
                                @Nullable FirebaseFirestoreException e) {
                attractionList.clear();
                for (DocumentSnapshot snapshot : queryDocumentSnapshots) {
                    Attraction attraction = snapshot.toObject(Attraction.class);
                    addAttractions(attraction);
                }
            }
        });
    }
Run Code Online (Sandbox Code Playgroud)

每次创建新对象时,我都会检索数据:

public AttractionList() {
        firestore.setFirestoreSettings(settings);
        reference = firestore.collection("attractions");
        attractionList = new ArrayList<>();
        retrieveData();
    }
Run Code Online (Sandbox Code Playgroud)

然后,如果我在创建时在我的活动中检查列表大小:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_attraction);
        Toolbar toolbar = findViewById(R.id.tb_attraction);
        setSupportActionBar(toolbar);

        //Creating POJO List and retrieving data
        attractionList = new AttractionList();
        Log.e("List Size: ", ""+attractionList.getAttractionList().size());
        //List Size: 0
    }
Run Code Online (Sandbox Code Playgroud)

但是,如果之后使用相同的Log time,则在任何按钮中:

@Override
    public void onBackPressed(){
        Log.e("List Size: ", ""+attractionList.getAttractionList().size());
        //List Size: 16
    }
Run Code Online (Sandbox Code Playgroud)

我并不是很想在每个Activity中检索数据,也不想创建将Object带入Activity之间的意图。有什么办法可以解决这个问题?

PS:这是我的第一篇文章。抱歉,如果我没有以正确的方式进行操作。非常感谢。

Ale*_*amo 5

您现在不能使用尚未加载的内容。Firestore会加载数据asynchronously,因为这可能需要一些时间。根据您的连接速度和状态,可能需要几百毫秒到几秒钟的时间才能获得该数据。如果要将类型的对象列表传递Attraction给另一个方法,只需在方法内部调用该方法onSuccess()并将该列表作为参数传递。因此,一个快速的解决方法是:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference attractionsRef = rootRef.collection("attractions");

attractionsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
    @Override
    public void onComplete(@NonNull Task<QuerySnapshot> task) {
        if (task.isSuccessful()) {
            List<Attraction> attractionsList = new ArrayList<>();
            for (QueryDocumentSnapshot document : task.getResult()) {
                Attraction attraction = document.toObject(Attraction.class);
                attractionsList.add(attraction);
            }
            methodToProcessTheList(attractionsList);
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

因此请记住,onSuccess()方法具有异步行为,这意味着甚至在从数据库获取数据之前就已调用该方法。如果要使用该attractionsList方法之外的方法,则需要创建自己的方法callback。为此,首先需要创建一个如下接口:

public interface MyCallback {
    void onCallback(List<Attraction> attractionsList);
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要创建一个实际上从数据库获取数据的方法。此方法应如下所示:

public void readData(MyCallback myCallback) {
    attractionsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {
                List<Attraction> attractionsList = new ArrayList<>();
                for (QueryDocumentSnapshot document : task.getResult()) {
                    Attraction attraction = snapshot.toObject(Attraction.class);
                    attractionsList.add(attraction);
                }
                myCallback.onCallback(attractionsList);
            }
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

最后,仅需简单地调用readData()method并将MyCallback接口的实例作为参数传递给您,如您所需要的那样:

readData(new MyCallback() {
    @Override
    public void onCallback(List<Attraction> attractionsList) {
        //Do what you need to do with your list
    }
});
Run Code Online (Sandbox Code Playgroud)

这是可以attractionsListonSuccess()方法外部使用该对象的唯一方法。有关更多信息,您也可以观看此视频