自动计算与 Firebase Firestore Flutter 中存储的地理坐标数据的距离

2023-12-19

我已在 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”类型的子类型仍然存在,并且显示距离的文本被拉伸为红色。如果可以的话,请指导最佳方法 - 它也可能对将来的某人有所帮助。


我的做法如下:

查询整个文档的方式如下:

//This a synchronus operation    
final data = await Firestore.instance
            .collection('collection_name')
            .getDocuments();

然后将所有文档传递到一个列表中: 自从DocumentSnapshot is a List<dynamic>

List doc = data.documents;

现在计算每个的距离LatLng在你的firestore与当前位置LatLng并继续将其附加到空的list在迭代中你可以使用它gridView:

List distanceList=[]; //define and empty list
doc.forEach((e){
double lat=e.data[ITEM_LATITUDE]; //asuming ITEM_LATITUDE is the field name in firestore doc.
double lng=e.data[ITEM_LONGITUDE];//asuming ITEM_LONGITUDE is the field name in firestore doc.
distanceList.add(your distance calculating function); //call this inside an async function if you are using await;
});

而不是使用异步gelocator.distance我写了一个函数dart使用“haversine”公式找到最短函数:

double calculateDistance (double lat1,double lng1,double lat2,double lng2){
    double radEarth =6.3781*( pow(10.0,6.0));
    double phi1= lat1*(pi/180);
    double phi2 = lat2*(pi/180);
    
    double delta1=(lat2-lat1)*(pi/180);
    double delta2=(lng2-lng1)*(pi/180);
    
    double cal1 = sin(delta1/2)*sin(delta1/2)+(cos(phi1)*cos(phi2)*sin(delta2/2)*sin(delta2/2));
    
   double cal2= 2 * atan2((sqrt(cal1)), (sqrt(1-cal1)));
    double distance =radEarth*cal2;
    
    return (distance);
    
}

This a synchronous function代码如下firestore doc.forEach();列表功能:

List distanceList; //define and empty list
doc.forEach((e){
double lat=e.data[ITEM_LATITUDE]; //asuming ITEM_LATITUDE is the field name in firestore doc.
double lng=e.data[ITEM_LONGITUDE];//asuming ITEM_LONGITUDE is the field name in firestore doc.
double distance = calculateDistance(currentLat,currentLng, lat,lng);
distanceList.add(distance);
});
//Now the distanceList would contain all the shortest distance between 
// current LatLng and all the other LatLng in your firestore documents:

记得清空distanceList在使用再次存储距离之前。


整个代码如下;

//Shortest Distance Function definition:
double calculateDistance (double lat1,double lng1,double lat2,double lng2){
double radEarth =6.3781*( pow(10.0,6.0));
double phi1= lat1*(pi/180);
double phi2 = lat2*(pi/180);
    
double delta1=(lat2-lat1)*(pi/180);
double delta2=(lng2-lng1)*(pi/180);
    
double cal1 = sin(delta1/2)*sin(delta1/2)+(cos(phi1)*cos(phi2)*sin(delta2/2)*sin(delta2/2));
    
double cal2= 2 * atan2((sqrt(cal1)), (sqrt(1-cal1)));
double distance =radEarth*cal2;
    
return (distance);
    
}

List distanceList; //list defination

// Call this function every time you want to calculate distance between currentLocation and all location in firestore.
void calculateDistanceAndStore(double currentLat, double currentLng) async{
distanceList=[];p;
final data = await Firestore.instance
            .collection('collection_name')
            .getDocuments();
doc.forEach((e){
double lat=e.data[ITEM_LATITUDE]; //asuming ITEM_LATITUDE is the field name in firestore doc.
double lng=e.data[ITEM_LONGITUDE];//asuming ITEM_LONGITUDE is the field name in firestore doc.
    double distance = calculateDistance(currentLat,currentLng, lat,lng);
    distanceList.add(distance);
    });
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自动计算与 Firebase Firestore Flutter 中存储的地理坐标数据的距离 的相关文章

随机推荐

  • 是否可以在没有 REST 请求的情况下创建 Kafka 连接器?

    是否可以在没有 REST 请求的情况下创建 Kafka 连接器 我已经通过 java 代码启动了我的工作程序 分布式 并希望我的连接器也随之启动 我不想使用 REST 调用 不是来自浏览器 也不是来自代码 来创建我的连接器 我只想要一个简单
  • codeigniter 数据库移动到另一个表

    如何解决这个 codeigniter 问题 我有一个数据库表 Mysql 我需要使用 Php Codeigniter 框架将其所有字段内容移动到另一个表 将数据从一个表插入到另一个可在我的模型和控制器中使用的表的语法是什么 我尝试使用这些
  • Angular 2 核心模块和功能模块的区别

    我不明白之间的区别core https angular io docs ts latest guide ngmodule html core module and feature https angular io docs ts lates
  • 标签“文件系统”出现问题

    出于娱乐原因 我编写了一个 PHP 类 它用标签对文件进行分类 而不是以分层方式进行分类 标签以 tag1 tag2 tagN MD5 EXTENSION 的形式存储在文件名本身中 因此我坚持使用FS OS 施加的字符限制 255 这是课程
  • WSL-2:哪些端口会自动转发?

    我已经研究 WSL 2 一段时间了 但并不完全了解主机和 WSL 2 区域之间的流量是如何路由的 在某些来源中 WSL 2 使用的所有端口似乎都会自动可供主机使用 比如在微软的这个教程 https learn microsoft com e
  • 在 Symfony 中防止 Doctrine 的查询缓存

    在我的 Symfony Doctrine 应用程序中 我有一个按 RANDOM 排序的查询 我多次调用相同的方法 但看起来查询的结果正在被缓存 这是我的相关代码 query table gt createQuery p gt select
  • 如何在 Chrome 应用程序中包含数据文件以供本机客户端模块读取

    如果我有一个 Chrome 打包应用程序 其中还包含 PNaCl NaCl 模块 是否有办法在打包应用程序中包含一些数据文件 然后 NaCl 模块将读入这些数据文件 我不需要编写任何文件 只需包含本机模块需要使用的一些数据文件即可 Java
  • Jruby 中的 Java 数组

    我有一个 Java 库 我正在从中提取一些数据 它输出一个 3D 数组 但是我无法用它做任何事情 D 5615a6e0 是我得到的回应 我尝试过映射它 arr arr map arr arr to a 但我什么也没得到 解析这个java数组
  • Android 稍后通知用户

    我想在android中创建一个应用程序 其中用户选择未来的某一天 然后 当那一天到来时 他会收到通知 我知道这可以通过日历或注释来完成 但这并不对我来说很重要 我有两个与前一个问题相关的问题 A 我该如何执行通知 我在其他地方读到过有关向用
  • 停止/取消执行 FFmpeg 命令

    Android 有可用的 FFmpeg Static 二进制 我们可以在 FFmpeg 执行某些操作时停止 取消某些 FFmpeg 执行 命令 https github com WritingMinds ffmpeg android jav
  • 为什么 jQuery 事件在就绪函数之外时不触发,即使文档已就绪?

    尽管 DOM 似乎已加载 控制台中显示 就绪 为什么在这种情况下单击事件未触发 document ready function console log ready p click function alert You clicked on
  • 如何在页面加载时逐个淡入图像?

    我创建了以下代码 在页面加载时向页面上的所有 div 添加 opacity 1 这样做时 所有图像都会在页面加载时看到 但我希望每个图像都慢慢淡入 并且在一个图像完全加载 可见后 我希望第二个图像加载完全相同 然后加载第三个图像 我怎样才能
  • Java中可以更改内部类的外部类实例吗?

    在Java中 每当创建内部类实例时 它都会与外部类的实例相关联 出于好奇 是否可以将内部类与外部类的另一个实例相关联 是的 这是可能的 尽管这对我来说听起来是一个非常糟糕的主意 这个想法是设置否则final使用反射指向外部实例的指针 不保证
  • 绘图不显示

    我有一个相当简单的 xml 文件 其中有一个图像按钮 该图像在图形布局 xml 设计器上显示良好 当我运行开发构建时显示良好 但一旦我创建签名的 apk 文件并运行它 图像就不再显示 这只是一个空按钮 我想不出原因 有什么想法吗 xml 文
  • LINQ to SQL 将不会生成可控制查询

    我正在使用 LINQ To Sql 不是实体框架 System Data Linq DataContext 库 访问 SQL Server 2005 数据库并使用 Net Framework 4 表 dbo Dogs 有一个类型为 CHAR
  • '{"errors":{"base":["禁止。需要用户。"]}}'

    大家好 我正在尝试上传它向我展示的用户个人资料图片 errors base 禁止 需要用户 这个错误请让我知道我做错了什么 QBContent uploadFileTask profilePic true new QBCallbackImp
  • docker swarm - 如何平衡 swarm 集群中已经运行的容器?

    我在 AWS 上有一个带有 2 个节点的 docker swarm 集群 我停止了这两个实例 最初启动了 swarm manager 然后启动了worker 在停止实例之前 我运行了一个服务 该服务在管理器和工作人员之间分配了 4 个副本
  • 保留标识符在编译的哪个阶段被保留?

    只是工作中的一点好奇心 在从事危险的工作时 我开始考虑各种编译器及其相关标准库的实现 以下是我的想法的进展 某些类别的标识符保留供 C 和 C 中的实现使用 编译器必须执行编译阶段 预处理 编译 链接 就好像它们是按顺序执行的一样 C 预处
  • 使用众多接口中的一个作为函数中的参数

    我有一个这样的函数 interface Interface1 one string interface Interface2 two string interface Interface3 three string type ManyInt
  • 自动计算与 Firebase Firestore Flutter 中存储的地理坐标数据的距离

    我已在 firestore 数据库中存储了项目的纬度和经度 字段为 item latitude 和 item longitude 因此 所有项目都有纬度和经度 我可以使用流来获取项目 例如 Stream