使用 Flutter 在 Firebase 中使用 Stream<QuerySnapshot> 检索数据

Posted

技术标签:

【中文标题】使用 Flutter 在 Firebase 中使用 Stream<QuerySnapshot> 检索数据【英文标题】:Retrieving Data with Stream<QuerySnapshot> in Firebase with Flutter 【发布时间】:2020-03-12 11:34:23 【问题描述】:

也许这是一个新手问题,但我正在学习颤振,并且一些东西,如 async、await、Future,还不适合我的想法。无论如何,我想做的是从“field.documents[index][”name”]”中获取值并建立一个列表。这是我的代码:

String productName;

Stream<QuerySnapshot> productRef = Firestore.instance
    .collection("stores")
    .document(name)
    .collection("products")
    .snapshots();
productRef.forEach((field) 
  field.documents.asMap().forEach((index, data) 
    productName = field.documents[index]["name"];
    //IF I PRINT HERE, IT SHOWS THE PRODUCTS. 
  );
);
BUT IF I PRINT HERE, I GOT A NULL VALUE

我想在 forEach 之外获取 productName。当我打印时,它首先打印空值。我也会发布我的整个功能:

List mapToList(DocumentSnapshot doc, List<DocumentSnapshot> docList) 
    if (docList != null) 
      List<Store> storeList = [];
      docList.forEach((document) 
        String name = document.data[StringConstant.nameField];
        num score = document.data[StringConstant.scoreField];
        String delivery = document.data[StringConstant.deliveryField];
        String photo = document.data[StringConstant.photoField];
        String description = document.data[StringConstant.descriptionField];
        String open = document.data[StringConstant.openField];
        String close = document.data[StringConstant.closeField];
        GeoPoint geoPoint = document.data[StringConstant.positionField]
            [StringConstant.geopointField];

        bool isOpen = document.data[StringConstant.isOpenField];
        final currentHour = DateTime.now();
        final openHour = DateTime.parse(open).hour;
        final closeHour = DateTime.parse(close).hour;
        int openMin = DateTime.parse(open).minute;
        int closeMin = DateTime.parse(close).minute;
        if (openHour <= currentHour.hour && currentHour.hour <= closeHour) 
          isOpen = true;
          if ((currentHour.hour == openHour && currentHour.minute < openMin) ||
              (currentHour.hour == closeHour &&
                  currentHour.minute > closeMin)) 
            isOpen = false;
          
         else 
          isOpen = false;
        
        final double meter = distance(
          LatLng(latitude, longitude),
          LatLng(geoPoint.latitude, geoPoint.longitude),
        );

        String productName;

        Stream<QuerySnapshot> productRef = Firestore.instance
            .collection("stores")
            .document(name)
            .collection("products")
            .snapshots();
        productRef.forEach((field) 
          field.documents.asMap().forEach((index, data) 
            productName = field.documents[index]["name"];
          );
        );

        if (meter <= range && isOpen == true) 
          Store otherStore = Store(name, photo, score.toDouble(), delivery,
              meter, description, productName, 10.0, "");
          storeList.add(otherStore);
        
      );
      return storeList;
     else 
      return null;
    
  

有人可以帮助我吗?我知道它与异步编程有关,但我正在学习。谢谢!!!

【问题讨论】:

【参考方案1】:

我要做的是在这里:

List<String> productName= [];

Stream<QuerySnapshot> productRef = Firestore.instance
    .collection("stores")
    .document(name)
    .collection("products")
    .snapshots();
productRef.forEach((field) 
  field.documents.asMap().forEach((index, data) 
    productName.add(field.documents[index]["name"]);
  );
);

您在查询之外初始化一个数组,以便每次“.forEach”迭代时都可以向其中添加一个字符串。您可以做什么而不是手动输入函数中的每个数据,您可以创建一个数据模型来将数据库中的数据存储到一个局部变量中,这比手动执行 field.documents['dataField'] 更灵活。这是一些有用的链接:https://medium.com/flutter-community/parsing-complex-json-in-flutter-747c46655f51

【讨论】:

是的,但是当我在 forEach 之外打印列表时,它仍然为 NULL,我打印了“[]”。我需要把它放在 forEach 之外。 你初始化了 Widget 中的 List(BuildContext 上下文)吗?在该函数之外初始化它,最好在 extends State 下方 伙计,我只需要更好地理解异步编程并从 forEach 内部到外部检索数据。 我想在这里帮助你。您需要在“小部件构建”之外初始化列表,因为如果您不这样做,它将继续重新初始化您在构建中初始化的值,这就是它可以一直返回 null 的原因。 我认识我的朋友。我真的很感激!我做了一些改变,现在我得到了外面的价值观。但是当我使用异步时,它不会构建我的列表。但是谢谢!!!

以上是关于使用 Flutter 在 Firebase 中使用 Stream<QuerySnapshot> 检索数据的主要内容,如果未能解决你的问题,请参考以下文章

使用flutter如何在同一个App中使用多个firebase实时数据库

无法在 Flutter 中使用 Firebase Auth 进行注册

使用存储和 cookie(不使用 Firebase)在 Flutter 中进行身份验证?

Flutter:如何在 [Firebase] 中使用 OR 条件获取流查询

在 iOS 中使用 LinkedIn + firebase auth + Flutter 登录

在flutter中处理链接并使用firebase动态链接导航