有什么方法可以让我的应用程序在继续执行代码之前等待从Firebase检索数据?

钛371

我的应用程序必须在ListView上显示名称列表。这些名称以以下方式存储在Cloud Firestore中:

集合:用户-文档:由用户UID整理-字段:名称(我必须注意,每个用户也有其他字段,但是我需要专门检索名称字段)

为此,我有第一个列表来检索所有文档或用户UID。然后,该第一个列表在for循环内使用,以检索用户集合中每个用户的名称。

但是,由于Firebase异步检索数据,因此通常会丢失一些名称,并且它们最终会以混乱的方式显示(与从第一个列表传递uid的顺序不一致)。

如果有人可以让我对如何使Firebase在继续进行for循环之前等待数据被检索有任何见解,将不胜感激!

以下是我的一些代码,可让您更好地了解自己在做什么。

代码的第一部分,成功检索了所有文档(uid)并将它们放在列表中

subTopicsDatabase.collection("schoolTopics").document(docKey).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                @Override
                public void onComplete(@NonNull Task<DocumentSnapshot> task) {

                    if (task.isSuccessful()){

            DocumentSnapshot document = task.getResult();

            if (document.exists()) {

                List<String> list = new ArrayList<>();

                Map<String, Object> map = document.getData();
                if (map != null) {
                    for (Map.Entry<String, Object> entry : map.entrySet()) {
                        list.add(entry.getValue().toString());
                    }

                }

                }});

代码的第二部分,由于Firebase的异步行为而无法使用。


for (int i = 0; i<list.size(); i++) {

                        String uid = list.get(i);

                        Toast.makeText(TutorsListActivity.this, uid, Toast.LENGTH_LONG).show();

                        subTopicsDatabase.collection("users").document(uid).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                            @Override
                            public void onSuccess(DocumentSnapshot documentSnapshot) {

                                if (documentSnapshot.exists()) {

                                    String stName = documentSnapshot.getString("name");
                                    ArrayAdapter<String> adapter = new ArrayAdapter<>(TutorsListActivity.this, R.layout.item_subtopic, testList);
                                    adapter.notifyDataSetChanged();
                                    sListView2.setAdapter(adapter);

                                }

                                }

                            });
                        }
班·马尔科维奇

您可以通过进行递归来模拟同步获取用户(该函数将其称为self,直到索引变大,然后uid列表的大小)。

因此,首先要定义适配器和字符串列表(代表用户名)。当您这样做时,您可以调用递归,它将填充您的List和notifyDataSetChanged。这是例子

// Define empty list of user names, which you will populate later with recursion
List<String> userNames = new ArrayList<String>();
// Connect adapter with empty list
ArrayAdapter<String> adapter = new ArrayAdapter<>(TutorsListActivity.this, R.layout.item_subtopic, userNames);
// Set adapter to ListView
sListView2.setAdapter(adapter);

// Call recursion with list of uids and starting index of 0
getUserSync(list, 0);


private void getUserSync(List<String> list, int i) {
    if (i < 0 || i > list.length - 1) {
        // If index i is out of bounds for list, we break the recursion
        return;
    }

    String uid = list.get(i);

    Toast.makeText(TutorsListActivity.this, uid, Toast.LENGTH_LONG).show();

    subTopicsDatabase.collection("users").document(uid).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
        @Override
        public void onSuccess(DocumentSnapshot documentSnapshot) {
            // When we load document, we fetch name and add it to the list which is connected to adapter
            // After that, we call adapter.notifyDataSetChanged which will update ui
            // When all that is done, we call getUserSync, to fetch user name for next uid
            if (documentSnapshot.exists()) {
                String stName = documentSnapshot.getString("name");
                if (stName != null) {
                    userNames.add(stName);
                    adapter.notifyDataSetChanged();
                }
            }
            getUserSync(list, i++);
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            // If enything goes wrong, we break the recursion
            return;
        }
    });
}

如果您有任何麻烦,请随时发表评论。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

有没有办法在继续代码之前等待异步应用程序脚本函数调用?

有什么方法可以在UWP应用程序和WPF应用程序之间共享代码?

我可以期望应用程序的构造函数在调用服务方法之前完全执行吗?

为什么数据没有显示在我的应用程序中,而我可以在 Firebase 中看到它?

我的应用程序没有从 firebase 子节点检索数据

有什么简单的方法可以直接在我的android应用程序上直接使用c / c ++源代码?

在继续程序之前等待代码运行

有什么方法可以限制执行在逻辑应用程序中运行?

我可以将 Firebase 用于只有数据库操作的应用程序吗?

在Google附近的连接API中,有什么方法可以在应用程序关闭时继续投放广告?

当我可以在Firebase中看到费用数据时,为什么我的应用程序中未显示费用数据?

有什么方法可以在我的Android应用程序布局中运行其他应用程序吗?

有什么方法可以验证我的Google Assistant应用程序的用户身份吗?

当我的应用程序意外关闭时,有什么方法可以获取错误日志?

有什么方法可以检查我的应用程序发送的电子邮件是否打开?

Web应用程序可以使用C#从Firebase数据库检索数据吗?

为什么我的Node应用程序在每次刷新后仍继续发送数据?

有什么方法可以将owin startup.cs配置为在全局asax应用程序启动之前运行?

如何在 Firebase 中设置规则,以便只有我的应用程序可以写入我的数据库 Firestore?

有什么方法可以更新Windows窗体应用程序?

为什么我的应用程序运行缓慢,是否有任何代码可以使该应用程序运行得更快?

ngFor循环继续执行并使用Firebase数据库在Ionic 3中使应用程序崩溃

从Xcode运行时,为什么我的ios应用程序似乎仅继续执行后台任务

有什么方法可以从Visual Studio代码扩展的Web视图导航到外部Windows应用程序?

在没有OnClickListener的情况下在Android应用程序中检索Firebase数据

有什么方法可以让所有人都只能通过应用程序访问Firestore数据库?

在 React Native 应用程序中从 firebase 检索数据

如何在我没有源代码的应用程序上执行UITesting?

即使我有睡眠线程,可可应用程序退出代码也不会执行