等到检索到 Firestore 数据以启动 Activity [英] Wait until Firestore data is retrieved to launch an activity

查看:20
本文介绍了等到检索到 Firestore 数据以启动 Activity的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've made a List of POJO Objects that get values from my Cloud Firestore database. This List is itself a Class having in mind to retrieve attributes everytime I create a new List. The thing is that the List is not filled in the on create activity but time after. I've tried adding loops, tasks, waits, but not getting the result desired. Here is how I retrieve my data satisfactorally:

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

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

I retrieve the data everytime I create a new Object:

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

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

Then, if I check the List size on my Activity on create:

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

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

But if I use the same Log time after, in any button:

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

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

I don't really want to retrieve data in every single Activity or creating intents to bring the Object between Activities. There is any way I could fix this?

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

PS: This is my first post. Sorry If I've haven't done it on the right way. Thank's a lot.

推荐答案

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

You cannot use something now that hasn't been loaded yet. Firestore loads data asynchronously, since it may take some time for this. Depending on your connection speed and the state, it may take from a few hundred milliseconds to a few seconds before that data is available. If you want to pass a list of objects of type Attraction to another method, just call that method inside onSuccess() method and pass that list as an argument. So a quick fix would be this:

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.要实现这一点,首先你需要创建一个这样的界面:

So remember, onSuccess() method has an asynchronous behaviour, which means that is called even before you are getting the data from your database. If you want to use the attractionsList outside that method, you need to create your own callback. To achieve this, first you need to create an interface like this:

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

然后你需要创建一个方法,它实际上是从数据库中获取数据.此方法应如下所示:

Then you need to create a method that is actually getting the data from the database. This method should look like this:

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 接口的实例作为参数传递给您需要的地方,如下所示:

In the end just simply call readData() method and pass an instance of the MyCallback interface as an argument wherever you need it like this:

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

这是在 onSuccess() 方法之外使用 attractionsList 对象的唯一方法.有关详细信息,您还可以查看此视频.

This is the only way in which you can use that attractionsList object outside onSuccess() method. For more informations, you can take also a look at this video.

这篇关于等到检索到 Firestore 数据以启动 Activity的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆