Firebase 在QuerySnapshot火基颤振自动增长列表的ForEach循环中进行计算,会导致错误的计算-错误的结果

Firebase 在QuerySnapshot火基颤振自动增长列表的ForEach循环中进行计算,会导致错误的计算-错误的结果,firebase,flutter,dart,Firebase,Flutter,Dart,我正在迭代一个querysnapshot,获取我用来计算距离的值。计算公式在for循环外进行了良好的测试。值/变量不为null(已完成null检查)。每次计算都会将计算出的数据迭代地传递到列表中。日志显示,对于每个完整的循环,列表中的数据都会加倍—例如,第一个循环的items count为60返回60次计算,第二次刷新输出为120—类似于此,或者根据加载的项目数随机增加。其次,计算是错误的。虽然这是一种基于等待和同步的方法,但我无法找出错误答案的原因以及如何删除重复项。在每次计算之前(在fore

我正在迭代一个querysnapshot,获取我用来计算距离的值。计算公式在for循环外进行了良好的测试。值/变量不为null(已完成null检查)。每次计算都会将计算出的数据迭代地传递到列表中。日志显示,对于每个完整的循环,列表中的数据都会加倍—例如,第一个循环的items count为60返回60次计算,第二次刷新输出为120—类似于此,或者根据加载的项目数随机增加。其次,计算是错误的。虽然这是一种基于等待和同步的方法,但我无法找出错误答案的原因以及如何删除重复项。在每次计算之前(在foreach循环之前),我确实会清除列表。 见下面的代码:

    Future<List> getDistancesModified() async {
    distanceList.clear();
    var x = await FirebaseFirestore.instance.collection(Str.ITEMS).get();
    if (x != null) {
      x.docs.forEach((doc) {
        itemAddressLat =
            double.tryParse(doc.data()[Str.ITEM_LATITUDE].toString()) ??
                -1.2921;
        itemAddressLong =
            double.tryParse(doc.data()[Str.ITEM_LONGITUDE].toString()) ??
                36.8219;

        distance = distanceBetween(
            itemAddressLat ?? defaultUserLat,
            itemAddressLong ?? defaultUserLong,
            usersCurrentLocationLat ??
                usersCurrentLocationLatFromDb ??
                defaultUserLat,
            usersCurrentLocationLong ??
                usersCurrentLocationLongFromDb ??
                defaultUserLong); //gives wrong answer inside the foreach loop but gives right answer if done separate from the for each loop for single values. The foreach is necessary to get all distances and pass them to a text through a future builder. 

        distance = distance.roundToDouble();
        distanceList.add(formatDistance(distance / 1000));//console prints grows for every rebuild
      });
    }
文本上显示的值是错误的,例如,当预期输出为200米或3公里时,实际不可能给出1113公里、4096公里等。计算仅在for each循环中进行


任何帮助都将不胜感激。这正在扼杀我的应用程序。

这个问题困扰了我一段时间,但下面的代码起了作用:

    Future<List> getDistances() async {
    distanceList = [];
    for (var i in items) {
      var s;
      var x = i.data()[Str.ITEM_LATITUDE].toString();
      var y = i.data()[Str.ITEM_LONGITUDE].toString();
      double d = distanceBetween(
          double.tryParse(x) ?? usersDefaultCityLat,
          double.tryParse(y) ?? usersDefaultCityLong,
          usersCurrentLocationLat ??
              usersHomeLocationLat ??
              usersDefaultCityLat,
          usersCurrentLocationLong ??
              usersHomeLocationLong ??
              usersDefaultCityLong);
      if (d < 454) {
        s = "Nearby";
      }
      if (d >= 454 && d < 1000) {
        d = d;
        s = d.toStringAsFixed(0) + " M";
      }
      if (d >= 1000) {
        s = (d / 1000).toStringAsFixed(0) + " KM";
      }
      distanceList.add(s);
    }
    return distanceList;
  }
  • 调用firebase数据库将项目放入列表是重复的-这是罪魁祸首:我看到了以下内容:列表项目和列表距离列表,所有的项目一个用于显示,一个用于获取纬度和经度以计算距离。这导致最终清单出现重复

  • 所有这些都与列表保持一定距离(注意,保持距离的文本被包装在交错的网格视图中,该视图已经在DocumentSnapshot的items列表中迭代,而最初,我也在文本小部件上使用相同的索引键(真正的问题)迭代另一个List distanceList。尽管如此,@jamesdlin指出,使用局部变量w这是可能的

    FutureBuilder(
     future: getDistances(),
     builder: (context, snapshot) {
       if (snapshot.hasData) {
         return Text(
           distanceList.length >
                   index
               ? distanceList[index]
                   .toString()
               : "",//THIS CHECK WAS NECESSARY AGAINST LIST LENGHTS NOT MATCHING IF ANY
           style: TextStyle(
               color: Colors.black,
               fontSize: 12.0,
               fontWeight:
                   FontWeight.w600),
         );
       } else {
         return Icon(Icons
             .location_searching);
       }
     },
    ),
    
  • 最后,老实说,我不得不将我的头埋在飘动的未来中——使用await和asnyc来理解这一切:感谢

  • 我希望这能教育一些人,并帮助任何人,防止他们在交错排列的网格视图(gridview/listview)中遇到重复列表,以及使用foreach而不是for循环(我不能肯定for是否真的解决了这个问题,但在其他地方也看到过类似的论证,而且我是安全的,因为foreach给出了空值,而不管链式等待的顺序如何。 这个问题应该指向我提出的类似问题:

  • 谢谢。新的bie在颤振,但不是在编码:)

  • 1.您试过调试它吗?2.一个可能的问题是,如果在进行中有一个较早的调用时再次调用
    getDistancesModified
    ,两个调用都会添加到相同的
    distanceList
    (在这种情况下,第二个调用调用
    distanceList.clear()
    没有帮助;它将清除一个已空的列表。)或者移动
    清除()
    wait
    之后调用to be,这样清除列表并添加到列表中就不会被中断,或者最好尽可能使用局部变量。你能发布调试输出吗?看看第3、5、9-68行以及第70和72行,其余都是重复的-只要重新启动应用程序,就好像getDistancesModified()被调用14次以上-请注意,getDistancesModified()的唯一引用位置是将来在for distance.File中显示文本的位置如下:
      Future<void> setUserLocationAddress() async {
     await getLocationFromLocationPackage();
     await setCountryCapitalCityLatlong();
     await getUserHomeAddress();
     await getDistances();
    
     @override
     void initState() {
     super.initState();
     setUserLocationAddress();
     }
    
    FutureBuilder(
     future: getDistances(),
     builder: (context, snapshot) {
       if (snapshot.hasData) {
         return Text(
           distanceList.length >
                   index
               ? distanceList[index]
                   .toString()
               : "",//THIS CHECK WAS NECESSARY AGAINST LIST LENGHTS NOT MATCHING IF ANY
           style: TextStyle(
               color: Colors.black,
               fontSize: 12.0,
               fontWeight:
                   FontWeight.w600),
         );
       } else {
         return Icon(Icons
             .location_searching);
       }
     },
    ),