微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Geoflutterfire函数内功能应仅返回Firestore数据库中的所有现有值,而不是永远监听

如何解决Geoflutterfire函数内功能应仅返回Firestore数据库中的所有现有值,而不是永远监听

我看到的所有有关geoFlutterfire内部功能的示例都将监听结果流,并在数据库中出现新位置时立即在地图上设置标记。即该流将连续不断地实时监视数据库中的新位置,永远不会结束。但是,我只需要读取数据库中所有现有的位置,然后处理结果列表即可。当我调用await stream.forEach()时,我发现await永远不会返回。同样,await stream.length()永不返回。我认为stream.listen也无济于事,因为没有“最后”事件。我能找到的唯一解决方案是:

    Stream<List<DocumentSnapshot>> stream = geo.collection(collectionRef: collRef)
          .within(center: center,radius: radius,field: "latlng");
    stream.timeout(Duration(seconds: 2),onTimeout: (eventSink) {
            print("timed out");
            eventSink.close();
          }).forEach(() {...});

,例如在2秒还有其他解决方案吗?我完全误导了吗?

解决方法

我通过不使用Streams并调用Query.get来解决此问题。因为我不想获取一个半径中的所有位置,而是在一个盒子中,所以我向Geoflutterfire添加了一个扩展名“ withinBox”,如下所示:

import 'package:geoflutterfire/geoflutterfire.dart';
// ignore: implementation_imports
import 'package:geoflutterfire/src/models/DistanceDocSnapshot.dart';
// ignore: implementation_imports
import 'package:geoflutterfire/src/Util.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

// like within,but sw/ne instead of circle/radius
extension GeoBox on GeoFireCollectionRef {
  static Query _collectionReference;

  Query _queryPoint(String geoHash,String field) {
    final end = '$geoHash~';
    final temp = _collectionReference;
    return temp.orderBy('$field.geohash').startAt([geoHash]).endAt([end]);
  }

  Future<List<DocumentSnapshot>> withinBox(Query collRef,String field,double minlat,double maxlat,double minlon,double maxlon) async {
    _collectionReference = collRef;
    GeoFirePoint center =
        GeoFirePoint((minlat + maxlat) / 2,(minlon + maxlon) / 2);
    double radius = center.distance(lat: maxlat,lng: maxlon);

    final precision = Util.setPrecision(radius);
    final centerHash = center.hash.substring(0,precision);
    final area = GeoFirePoint.neighborsOf(hash: centerHash)..add(centerHash);

    Iterable<Future<List<DistanceDocSnapshot>>> queries = area.map((hash) {
      final tempQuery = _queryPoint(hash,field);
      return tempQuery.get().then((QuerySnapshot querySnapshot) {
        return querySnapshot.docs
            .map((element) => DistanceDocSnapshot(element,null))
            .toList();
      });
    });

    List<DocumentSnapshot> filtered = [];
    await Future.wait(
        queries.map((Future<List<DistanceDocSnapshot>> query) async {
      List<DistanceDocSnapshot> list = await query;
      var mappedList = list.map((DistanceDocSnapshot distanceDocSnapshot) {
        // split and fetch geoPoint from the nested Map
        final fieldList = field.split('.');
        var geoPointField =
            distanceDocSnapshot.documentSnapshot.data()[fieldList[0]];
        final GeoPoint geoPoint = geoPointField['geopoint'];
        bool insideBox = geoPoint.latitude > minlat &&
            geoPoint.latitude < maxlat &&
            geoPoint.longitude > minlon &&
            geoPoint.longitude < maxlon;
        distanceDocSnapshot.distance = insideBox ? 0 : 9999999;
        return distanceDocSnapshot;
      });

      final filteredList = mappedList
          .where((DistanceDocSnapshot doc) => doc.distance == 0)
          .toList();
      filtered.addAll(filteredList.map((element) => element.documentSnapshot));
    }));
    return filtered;
  }
}

这将调用tempQuery.get(),其中原始的inside()将调用_createStream(tempQuery)。 该代码实际上执行9个查询:对中心正方形和8个相邻正方形。性能的关键在于“ await Future.wait(queries.map())”调用,该调用可以并行执行所有9个查询。

尽管我对这段代码感到很满意,但是现在timeout()已经消失了,我还是很乐意为原始问题提供一个答案。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。