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

已移除的Location Change Listener仍持续广播事件问题求助

问题描述

我实现了如下LocationListener接口:

class LocationListener(eventManager: RoadSnappedLocationProviderEventManager): RoadSnappedLocationProvider.LocationListener {
    var eventMananagerRef: RoadSnappedLocationProviderEventManager? = null
    init{
        eventMananagerRef = eventManager;
    }
    override fun onLocationChanged(p0: Location?) {
        Log.d("TZ", ("TZZZ  $p0.toString()"))
        val params: WritableMap = Arguments.createMap()
        params.putString("message", p0.toString())
        eventMananagerRef?.sendEvent(LOCATION_UPDATE_RECEIVED, params)
    }

    override fun onRawLocationUpdate(p0: Location?) {
        val params: WritableMap = Arguments.createMap()
        eventMananagerRef?.sendEvent(LOCATION_UPDATE_RECEIVED, params)
    }
}

并通过以下代码将其附加到NavigationApi.getRoadSnappedLocationProvider:

override fun onNavigatorReady(navigator: Navigator) {
                mNavigator = navigator
                locationListenerRef = LocationListener(eventManager)
                Log.d("TZ starting snapped ", locationListenerRef.toString())
                NavigationApi.getRoadSnappedLocationProvider(reactContext?.currentActivity?.application ?: Application()).addLocationListener(locationListenerRef)
            }

监听器正常触发位置变更事件,但调用移除方法后,事件处理器仍持续触发:

fun removeLocationListenerProvider(promise: Promise) {
        try {
            Log.d("TZ", ("REMOVING LOCATION LISTENER + ${locationListenerRef.toString()}"))
            NavigationApi.getRoadSnappedLocationProvider(reactContext?.currentActivity?.application ?: Application()).removeLocationListener(locationListenerRef)
            locationListenerRef = null
            Log.d("TZ", "REMOVED LOCATION LISTENER")
        } catch(e: Exception) {
            Log.d("TZ", e.toString())
        }
    }
解决方案
  • 复用同一个RoadSnappedLocationProvider实例
    核心问题是你每次调用NavigationApi.getRoadSnappedLocationProvider()都会获取新的实例,添加和移除监听器操作的不是同一个Provider对象,导致移除无效。解决方法是在初始化时保存Provider的引用,后续所有操作都复用该实例:

    // 类成员变量保存Provider实例
    private var locationProvider: RoadSnappedLocationProvider? = null
    
    override fun onNavigatorReady(navigator: Navigator) {
        mNavigator = navigator
        locationListenerRef = LocationListener(eventManager)
        // 初始化并保存Provider实例
        locationProvider = NavigationApi.getRoadSnappedLocationProvider(reactContext?.currentActivity?.application ?: Application())
        Log.d("TZ starting snapped ", locationListenerRef.toString())
        locationProvider?.addLocationListener(locationListenerRef)
    }
    
    fun removeLocationListenerProvider(promise: Promise) {
        try {
            Log.d("TZ", ("REMOVING LOCATION LISTENER + ${locationListenerRef.toString()}"))
            // 使用保存的Provider实例移除监听器
            locationProvider?.removeLocationListener(locationListenerRef)
            locationListenerRef = null
            locationProvider = null // 不再使用时可置空释放资源
            Log.d("TZ", "REMOVED LOCATION LISTENER")
            promise.resolve(null)
        } catch(e: Exception) {
            Log.d("TZ", e.toString())
            promise.reject("REMOVE_ERROR", e.message)
        }
    }
    
  • 验证监听器的对象相等性
    确保LocationListener的equals()和hashCode()方法正确实现(如果自定义了这些方法),否则Provider可能无法识别要移除的是同一个监听器实例。你当前使用的是同一个监听器引用,这一点没问题,但如果后续有复用场景需要注意。

  • 确保移除操作在主线程执行
    部分Android导航SDK要求回调相关操作在主线程执行,可将移除逻辑切换到主线程:

    fun removeLocationListenerProvider(promise: Promise) {
        reactContext?.currentActivity?.runOnUiThread {
            try {
                Log.d("TZ", ("REMOVING LOCATION LISTENER + ${locationListenerRef.toString()}"))
                locationProvider?.removeLocationListener(locationListenerRef)
                locationListenerRef = null
                locationProvider = null
                Log.d("TZ", "REMOVED LOCATION LISTENER")
                promise.resolve(null)
            } catch(e: Exception) {
                Log.d("TZ", e.toString())
                promise.reject("REMOVE_ERROR", e.message)
            }
        } ?: promise.reject("ACTIVITY_NULL", "Current activity reference is null")
    }
    

内容的提问来源于stack exchange,提问作者Tzvetlin Velev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 08:05:29