如何解决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 举报,一经查实,本站将立刻删除。