Flutter Firebase如何正确比较Firestore中两个存储字段的数值
解决方法
核心问题
你当前代码中的对比逻辑是直接对两个字符串字面量做相等判断,'latitude' == 'currlatitude'永远返回false,完全没有读取Firebase中存储的实际数值,同时经纬度属于浮点数,直接用==判断相等会因为GPS微小误差导致误判,需要增加精度容错。
修改步骤
- 确保你的
UserModel类中已经定义了与Firebase字段对应的latitude、longitude属性,用于存储基准位置数值 - 将对比逻辑移到位置更新的监听回调中,保证每次位置更新后都用最新的数值做对比
- 浮点数对比增加误差容忍范围,推荐设置0.00001的误差阈值,对应1米左右的普通定位误差区间
- 修正闹钟调用的非法参数,同时避免重复注册闹钟
修正后的代码示例
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
相关产品推荐
相关产品推荐

