【问题标题】:Firebase Firestore get data from collectionFirebase Firestore 从集合中获取数据
【发布时间】:2018-03-24 04:53:36
【问题描述】:

我想从我的 Firebase Firestore 数据库中获取数据。我有一个名为 user 的集合,每个用户都有一些相同类型的对象的集合(我的 Java 自定义对象)。我想在创建 Activity 时用这些对象填充我的 ArrayList。

private static ArrayList<Type> mArrayList = new ArrayList<>();;

在 onCreate() 中:

getListItems();
Log.d(TAG, "onCreate: LIST IN ONCREATE = " + mArrayList);
*// it logs empty list here

调用方法以获取要列出的项目:

private void getListItems() {
    mFirebaseFirestore.collection("some collection").get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot documentSnapshots) {
                    if (documentSnapshots.isEmpty()) {
                        Log.d(TAG, "onSuccess: LIST EMPTY");
                        return;
                    } else {
                        for (DocumentSnapshot documentSnapshot : documentSnapshots) {
                            if (documentSnapshot.exists()) {
                                Log.d(TAG, "onSuccess: DOCUMENT" + documentSnapshot.getId() + " ; " + documentSnapshot.getData());
                                DocumentReference documentReference1 = FirebaseFirestore.getInstance().document("some path");
                                documentReference1.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                                    @Override
                                    public void onSuccess(DocumentSnapshot documentSnapshot) {
                                        Type type= documentSnapshot.toObject(Type.class);
                                        Log.d(TAG, "onSuccess: " + type.toString());
                                        mArrayList.add(type);
                                        Log.d(TAG, "onSuccess: " + mArrayList);
                                        /* these logs here display correct data but when
                                         I log it in onCreate() method it's empty*/
                                    }
                                });
                            }
                        }
                    }
                }
            }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Toast.makeText(getApplicationContext(), "Error getting data!!!", Toast.LENGTH_LONG).show();
        }
    });
}

【问题讨论】:

  • 由于获取响应需要时间,所以一开始它显示为空,所以如果还有其他问题,请更具体地说明您的问题。
  • 不,这不是问题,因为我告诉过你我的列表中填满了最后一个 onSuccess 方法中的项目,我在日志中看到了,但在 onCreate 方法中它是空的
  • 您仅在 onCreate 中获取数据,并且需要时间来获取它,因此您在 onCreate 中的日志甚至在获取数据之前就已运行。
  • @Slaven Petkovic 如果需要,请检查我的更新代码...

标签: java android arraylist google-cloud-firestore


【解决方案1】:

get() 操作返回一个Task&lt;&gt;,这意味着它是一个异步操作。调用getListItems() 只是启动操作,它不会等待它完成,这就是为什么你必须添加成功和失败的监听器。

虽然对于操作的异步性质您无能为力,但您可以按如下方式简化代码:

private void getListItems() {
    mFirebaseFirestore.collection("some collection").get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot documentSnapshots) {
                    if (documentSnapshots.isEmpty()) {
                        Log.d(TAG, "onSuccess: LIST EMPTY");
                        return;
                    } else {
                        // Convert the whole Query Snapshot to a list
                        // of objects directly! No need to fetch each
                        // document.
                        List<Type> types = documentSnapshots.toObjects(Type.class);   

                        // Add all to your list
                        mArrayList.addAll(types);
                        Log.d(TAG, "onSuccess: " + mArrayList);
                    }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Toast.makeText(getApplicationContext(), "Error getting data!!!", Toast.LENGTH_LONG).show();
                }
            });
}

【讨论】:

  • 我也有类似的情况,除了代码之后,我想获取ArrayList的大小。问题是,如果我检查 onSuccess() 中的大小,它会给出正确的值,但我不能从那里返回,因为它在侦听器中。但是,如果我在该方法中的所有代码之后进行检查,它会返回 0,因为此时异步任务尚未完成..
【解决方案2】:

试试这个..工作正常。下面的函数也会从 firebse 获取实时更新..

db = FirebaseFirestore.getInstance();


        db.collection("dynamic_menu").addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {

                if (e !=null)
                {

                }

                for (DocumentChange documentChange : documentSnapshots.getDocumentChanges())
                {
                 String   isAttendance =  documentChange.getDocument().getData().get("Attendance").toString();
                 String  isCalender   =  documentChange.getDocument().getData().get("Calender").toString();
                 String isEnablelocation = documentChange.getDocument().getData().get("Enable Location").toString();

                   }
                }
        });

更多参考 :https://firebase.google.com/docs/firestore/query-data/listen

如果您不希望实时更新,请参阅下面的文档

https://firebase.google.com/docs/firestore/query-data/get-data

【讨论】:

    【解决方案3】:
        db.collection("users").get().then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
            console.log(`${doc.id} => ${doc.data()}`);
        });
    

    来源:- https://firebase.google.com/docs/firestore/quickstart

    【讨论】:

    • 你发布了一个 android 问题的节点 js 代码
    • 很抱歉,但它是如何获得投票的? ???
    【解决方案4】:

    这是一个简化的例子:

    在 Firebase 中创建一个集合“DownloadInfo”。

    并在其中添加一些包含这些字段的文档:

    文件名(字符串), id(字符串), 大小(数字)

    创建你的类:

    public class DownloadInfo {
        public String file_name;
        public String id;
        public Integer size;
    }
    

    获取对象列表的代码:

    FirebaseFirestore db = FirebaseFirestore.getInstance();
    
    db.collection("DownloadInfo")
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                         if (task.getResult() != null) {
                                List<DownloadInfo> downloadInfoList = task.getResult().toObjects(DownloadInfo.class);
                                for (DownloadInfo downloadInfo : downloadInfoList) {
                                    doSomething(downloadInfo.file_name, downloadInfo.id, downloadInfo.size);
                                }
                            }
                        }
                    } else {
                        Log.w(TAG, "Error getting documents.", task.getException());
                    }
                }
            });
    

    【讨论】:

      【解决方案5】:

      假设我们有一个包含数组类型属性的文档。这个数组被命名为users 并包含一些用户对象。 User 类非常简单,只包含两个属性,如下所示:

      class User {
          public String name;
          public int age;
      
          public User(String name, int age) {
              this.name = name;
              this.age = age;
          }
      }
      

      这是数据库结构:

      所以我们的目标是将users 数组编码为List&lt;User&gt;。为此,我们需要在文档上附加一个监听器并使用get() 调用:

      FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
      CollectionReference applicationsRef = rootRef.collection("applications");
      DocumentReference applicationIdRef = applicationsRef.document(applicationId);
      applicationIdRef.get().addOnCompleteListener(task -> {
          if (task.isSuccessful()) {
              DocumentSnapshot document = task.getResult();
              if (document.exists()) {
                  List<Map<String, Object>> users = (List<Map<String, Object>>) document.get("users");
              }
          }
      });
      

      要真正从users 数组中获取值,我们调用:

      document.get("users")
      

      我们将对象转换为List&lt;Map&lt;String, Object&gt;&gt;。所以这个对象实际上是一个地图列表。确实,我们可以遍历 Map,取出数据并自己创建List&lt;User&gt;。但由于 DocumentSnapshot 包含 get() 方法的不同风格,根据每种数据类型,getString()getLong()getDate() 等,如果我们也有一个getList() 方法会非常有帮助,但不幸的是我们没有。所以是这样的:

      List<User> users = document.getList("users");
      

      不可能。那我们怎么还能得到一个List呢?

      最简单的解决方案是创建另一个仅包含List&lt;User&gt; 类型属性的类。它看起来像这样:

      class UserDocument {
          public List<User> users;
      
          public UserDocument() {}
      }
      

      而直接获取列表,只需要以下几行代码:

      applicationIdRef.get().addOnCompleteListener(task -> {
          if (task.isSuccessful()) {
              DocumentSnapshot document = task.getResult();
              if (document.exists()) {
                  List<User> users = document.toObject(UserDocument.class).users;
                  //Use the the list
              }
          }
      });
      

      获取自:How to map an array of objects from Cloud Firestore to a List of objects?

      【讨论】:

        【解决方案6】:

        这是获取列表的代码。 由于这是一个异步任务,因此需要时间,这就是列表大小一开始显示为空的原因。 但是包含缓存数据的来源将使之前的列表(以及它的大小)能够在内存中,直到执行下一个任务。

        Source source = Source.CACHE;
                firebaseFirestore
                        .collection("collectionname")
                        .get(source)
                        .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                            @Override
                            public void onSuccess(QuerySnapshot documentSnapshots) {
                                if (documentSnapshots.isEmpty()) {
        
                                    return;
                                } else {
                                    // Convert the whole Query Snapshot to a list
                                    // of objects directly! No need to fetch each
                                    // document.
                                    List<ModelClass> types = documentSnapshots.toObjects(ModelClass.class);
                                    // Add all to your list
                                    mArrayList.addAll(types);
                                }
        
                            }
                        })
                        .addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
        
                            }
                        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-11-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-03
          • 2018-11-06
          相关资源
          最近更新 更多