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

GeoQuery.removeAllListeners无效致Firebase重复数据问题

问题原因

数据库出现重复数据的核心原因是监听器移除逻辑的作用对象错误,没有真正清理掉旧查询的监听,导致多轮扩大半径生成的查询同时在后台运行,重复触发写入逻辑:

  • 每次进入getTheClosestDriver()方法时,你都会通过geoFire.queryAtLocation()创建一个全新的GeoQuery实例,再把这个新实例赋值给成员变量geoQuery
  • 紧接着调用geoQuery.removeAllListeners()时,操作的是刚创建的、还没绑定任何监听器的新实例,上一轮递归生成的旧GeoQuery实例的引用已经被新值覆盖,你根本无法访问到旧实例,上面绑定的监听器完全没有被移除
  • 所有没被清理的旧半径查询会持续在后台监听位置变化,只要匹配到符合条件的司机就会触发onKeyEntered回调,重复执行写入司机关联信息的逻辑,最终导致数据库出现重复数据
  • 额外隐患:成功找到司机后,你也没有主动移除当前GeoQuery的监听器,查询会一直保持运行,白白消耗资源,还可能在后续流程中触发不必要的回调。
修复方案

调整代码执行顺序,保证创建新查询前先清理旧查询的监听器,找到司机后立刻终止查询,修复后的核心代码如下:

private GeoQuery geoQuery;

private void getTheClosestDriver() {
    // 优先清理上一轮残留的旧查询监听器,再创建新查询
    if (geoQuery != null) {
        geoQuery.removeAllListeners();
    }
    GeoFire geoFire = new GeoFire(driverAvailableRef);
    geoQuery = geoFire.queryAtLocation(new GeoLocation(customerPickUpLocation.latitude,customerPickUpLocation.longitude),radius);
    
    geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
        @Override
        public void onKeyEntered(String key, GeoLocation location) {
            if (!driverFound && requestType){
                driverFound = true;
                // 找到司机后第一时间移除所有监听,终止查询,避免后续重复触发
                geoQuery.removeAllListeners();
                
                driverFoundID = key;
                driverRef = FirebaseDatabase.getInstance().getReference().child("Users").child("Drivers").child(driverFoundID);

                HashMap driverMap = new HashMap();
                driverMap.put("customerFoundId",customerID);
                driverRef.updateChildren(driverMap);
                
                gettingTheDriverLocation();
            }

        }

        @Override
        public void onKeyExited(String key) {}

        @Override
        public void onKeyMoved(String key, GeoLocation location) {}

        @Override
        public void onGeoQueryReady() {
            if (!driverFound){
                radius = radius + 1;
                getTheClosestDriver();
                bookARide.setText("Searching For a Driver Location");
            }
        }

        @Override
        public void onGeoQueryError(DatabaseError error) {
            Toast.makeText(CustomerMapsActivity.this,error.getMessage(),Toast.LENGTH_LONG).show();
        }
    });
}
额外优化建议
  • 用户取消叫车、退出当前页面时,也要主动调用geoQuery.removeAllListeners()清理监听,避免内存泄漏和后台无效查询
  • 给搜索半径设置合理上限,比如最大不超过10公里,避免无限递归扩大搜索范围造成不必要的性能消耗

内容的提问来源于stack exchange,提问作者Ukeme Elijah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:06:29