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

时间:2018-06-01 19:54:32

标签: java android firebase google-cloud-firestore

我已经制作了一个POJO对象列表,它从我的Cloud Firestore数据库中获取值。此List本身就是一个类,每次创建新List时都要检索属性。问题是列表没有填写在创建活动上,而是在时间之后。我已经尝试添加循环,任务,等待,但没有得到所需的结果。以下是我如何令人满意地检索我的数据:

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);
                }
            }
        });
    }

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

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

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

@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
    }

但如果我在任何按钮之后使用相同的日志时间:

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

我真的不想在每个Activity中检索数据或创建意图以在活动之间引入Object。有什么办法可以解决这个问题吗?

PS:这是我的第一篇文章。对不起,如果我没有以正确的方式做到这一点。非常感谢。

1 个答案:

答案 0 :(得分:1)

您现在无法使用尚未加载的内容。 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);
        }
    }
});

请记住,onSuccess()方法具有异步行为,这意味着甚至在从数据库获取数据之前就会调用它。如果您想在该方法之外使用attractionsList,则需要创建自己的callback。要实现这一点,首先需要创建一个这样的界面:

public interface MyCallback {
    void onCallback(List<Attraction> attractionsList);
}

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

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);
            }
        }
    });
}

最后,只需调用readData()方法并将MyCallback接口的实例作为参数传递给任何需要的地方,如下所示:

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

这是您可以在attractionsList方法之外使用onSuccess()对象的唯一方法。有关更多信息,您还可以查看此 video