【发布时间】:2020-12-22 08:54:03
【问题描述】:
我已在 firestore 数据库中存储了项目的纬度和经度(字段为:item_latitude 和 item_longitude)。因此,所有项目都有纬度和经度。我可以使用流来获取项目,例如:
Stream<QuerySnapshot> getItems() async* {
yield* FirebaseFirestore.instance.collection("items").snapshots();
}
使用 StreamBuilder 或 FutureBuilder,我可以获得项目的单个属性,例如纬度和经度。 Geolocator有一种计算距离的方法,也是一种未来:
double distance = await geolocator.distanceBetween(lat, long, lat1, long1);
我能够获取用户的当前位置,在这种情况下它是 lat1、long1(这是一个单独的记录)。问题是:Strem getItems 获取纬度和经度流,对于每个项目,我需要参考当前位置计算其当前距离。这意味着,例如在 GridView 中遍历项目时,我需要计算并显示距离。 我以抽象的方式编写了这个问题,以便答案将解决如何基于同步数据流进行异步计算,以便在数据显示在页面的构建部分中时,计算是在外部完成的,因为不是,构建不会接受同步的异步计算。 我的尝试导致了以下结果:第一次尝试:
child: StreamBuilder(
stream: FetchItems().getItems(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text("KE");
}
if (snapshot.hasData) {
DocumentSnapshot data = snapshot.data.docs[index];
double lat = data.data()[Str.ITEM_LATITUDE];
double long = data.data()[Str.ITEM_LATITUDE];
return
Text(getDistance(usersCurrentLocationLat,usersCurrentLocationLong,lat,long).toString());
//This fails and returns on the Text place holder the following: Instance of 'Future<dynamic>'
}
}),
我的第二次尝试如下:
child: StreamBuilder(
stream: FetchItems().getItems(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text("KE");
}
if (snapshot.hasData) {
DocumentSnapshot data = snapshot.data.docs[index];
double lat = data.data()[Str.ITEM_LATITUDE];
double long = data.data()[Str.ITEM_LATITUDE];
double x = getDistance(usersCurrentLocationLat,usersCurrentLocationLong,lat,long);
return Text(x.toString());
//This fails and gives erro: type 'Future<dynamic>' is not a subtype of type 'double'
}
}),
进一步调查表明,以下用于获取当前位置并在 iniState 中引用的方法实际上确实获取了值(假设 Gps 在场外启用):
_getUserCurrentLocation() {
final Geolocator geolocator = Geolocator()..forceAndroidLocationManager;
geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best).then(
(Position position) {
setState(
() {
_currentPosition = position;
usersCurrentLocationLat = _currentPosition.latitude;
usersCurrentLocationLong = _currentPosition.longitude;
//a system print here returns current location as 0.3714267 32.6134379 (same for the
//StreamBuilder)
},
);
},
).catchError((e) {
print(e);
});
}
以下是计算距离的方法 - 使用提供的 Geolocator distanceBetween() 方法。
getDistance(double lat, double long, double lat1, double long1) async {
return distance = await geolocator.distanceBetween(lat, long, lat1, long1);
}
@override
void initState() {
super.initState();
_getUserCurrentLocation();
}
我将如何遍历获取它们的纬度和经度的项目,计算距离并将其显示在文本上?这是一个普遍的问题,可能的解决方案组合将非常受欢迎。请注意,在 StreamBuilder 中,我实际上可以使用以下命令打印以控制每个坐标:
print("FROM CURRENT LOCATION HERE ----" + usersCurrentLocationLat.toString() +"::::::::" +
usersCurrentLocationLong.toString());
print("FROM STREAM FROM DB SURE ----" + lat.toString() +"::::::::" + long.toString());
在控制台中为数据库中的所有项目打印为(一个示例):
I/flutter (30351): FROM CURRENT LOCATION HERE ----0.3732317::::::::32.6128083
I/flutter (30351): FROM STREAM FROM DB SURE ----2.12323::::::::2.12323
证明坐标是实际得到的。 主要错误:“Future”类型不是“double”类型的子类型,并且显示距离的文本被拉伸为红色。如果可以,请指导最佳方法 - 它也可能对将来的某人有所帮助。
【问题讨论】:
-
index在snapshot.data.docs[index]中使用的是什么?可以使用什么范围的值? -
对于流,FetchItems().getItems(),对于每个快照,我们使用如下索引进行迭代: DocumentSnapshot data = snapshot.data.docs[index]; index 来自:StaggeredGridView.countBuilder( itemBuilder: (BuildContext context, int index) 项目显示在网格中。问题出在:类型“Future”不是“double”类型的子类型 - 如如何获取getDistance 中的未来(因为它有等待)并在文本显示中传递与双精度相同的值。
-
index的值是多少?是 0、100、10000 吗?可以使用什么范围的值? -
在网格中,我们首先得到计数,所以如果项目是 3 或 4 或 n,那么我们迭代并显示我们想要的。 itemCount: items.length, 被传递: StaggeredGridView.countBuilder(scrollDirection: Axis.vertical, shrinkWrap: true, controller: scrollController, crossAxisCount: 4, itemCount: items.length, itemBuilder: (BuildContext context, int index)
-
带有索引的迭代工作完美,这就是为什么打印到控制台工作完美,如果在我的应用程序中选择不同的项目,地理坐标将显示在控制台上,而不是在文本(距离计算基本上不起作用,因为它期待未来。