You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Firebase如何正确比较Firestore中两个存储字段的数值

解决方法

核心问题

你当前代码中的对比逻辑是直接对两个字符串字面量做相等判断,'latitude' == 'currlatitude'永远返回false,完全没有读取Firebase中存储的实际数值,同时经纬度属于浮点数,直接用==判断相等会因为GPS微小误差导致误判,需要增加精度容错。

修改步骤

  1. 确保你的UserModel类中已经定义了与Firebase字段对应的latitude、longitude属性,用于存储基准位置数值
  2. 将对比逻辑移到位置更新的监听回调中,保证每次位置更新后都用最新的数值做对比
  3. 浮点数对比增加误差容忍范围,推荐设置0.00001的误差阈值,对应1米左右的普通定位误差区间
  4. 修正闹钟调用的非法参数,同时避免重复注册闹钟

修正后的代码示例

Future<void> _listenLocation() async {
  // 先取消已存在的订阅避免重复监听
  _locationSubscription?.cancel();
  _locationSubscription = location.onLocationChanged.handleError((onError) {
    print(onError);
    _locationSubscription?.cancel();
    setState(() {
      _locationSubscription = null;
    });
  }).listen((loc.LocationData currentlocation) async {
    // 上传当前实时位置到Firebase
    await FirebaseFirestore.instance.collection('users').doc(user!.uid).set({
      'currlatitude': currentlocation.latitude,
      'currlongitude': currentlocation.longitude,
    }, SetOptions(merge: true));

    // 读取基准位置(如果基准位置会动态修改,可在这里实时拉取Firebase最新数据,不用本地缓存的loggedInUser)
    double baseLat = loggedInUser.latitude!;
    double baseLng = loggedInUser.longitude!;
    double currentLat = currentlocation.latitude;
    double currentLng = currentlocation.longitude;

    // 带精度容错的数值对比
    const precisionThreshold = 0.00001;
    bool latMatch = (currentLat - baseLat).abs() < precisionThreshold;
    bool lngMatch = (currentLng - baseLng).abs() < precisionThreshold;

    // 先取消已存在的闹钟避免重复注册
    await AndroidAlarmManager.cancel(alarmId);
    if (latMatch && lngMatch) {
      // 位置匹配,停止告警
      await AndroidAlarmManager.periodic(
        const Duration(seconds: 1), 
        alarmId, 
        stopAlarm
      );
    } else {
      // 位置不匹配,触发告警
      await AndroidAlarmManager.periodic(
        const Duration(seconds: 2), 
        alarmId, 
        fireAlarm
      );
    }
  });
}

注意事项

  • 注意字段名大小写对应:如果你的Firebase中基准纬度字段是首字母大写的Latitude,要确保UserModel映射时字段名完全一致,否则会读取不到数值
  • 如果基准位置会在其他端/其他页面修改,建议不要使用initState中缓存的loggedInUser,可在对比前实时拉取一次Firebase用户文档的最新数据,避免用旧数据判断
  • AndroidAlarmManager的周期参数不能设置为0,最小合法值为1秒

内容的提问来源于stack exchange,提问作者Michelle Pui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 09:45:02