已移除的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
相关产品推荐
相关产品推荐

