使用geofence_flutter:^2.0.0重启服务时触发Stream已监听的Bad State错误
问题解决:geofence_flutter重启服务时Stream重复监听报错
错误原因
Geofence.getGeofenceStream()返回的是单订阅流,这类流仅允许被监听一次。当你第二次调用locationPunch()时,再次调用listen()就会触发Bad state: Stream has already been listened to错误。
修复方案
方案1:将单订阅流转为广播流
通过asBroadcastStream()把原流转为支持多订阅的广播流,即可实现多次监听:
locatoinPunch() async { await Geofence.startGeofenceService( pointedLatitude: locLat, pointedLongitude: locLon, radiusMeter: locRad, eventPeriodInSeconds: 10, ); // 转为广播流后支持多次监听 Geofence.getGeofenceStream().asBroadcastStream().listen((GeofenceEvent event) { // 直接用枚举常量判断,比toString更可靠 if (event == GeofenceEvent.exit) { awesomeDialog( title: "Geofence Error", message: "Punch from Wrong Location.", okBtnString: "Ok", ); } else if (event == GeofenceEvent.enter) { Geofence.stopGeofenceService(); locationPunch2(); } }); }
方案2:保存订阅对象,重启前取消订阅
在类中声明StreamSubscription变量,每次启动服务前先取消之前的订阅:
StreamSubscription? _geofenceSubscription; locatoinPunch() async { // 先取消已有订阅(如果存在) await _geofenceSubscription?.cancel(); await Geofence.startGeofenceService( pointedLatitude: locLat, pointedLongitude: locLon, radiusMeter: locRad, eventPeriodInSeconds: 10, ); // 保存新的订阅对象 _geofenceSubscription = Geofence.getGeofenceStream().listen((GeofenceEvent event) { if (event == GeofenceEvent.exit) { awesomeDialog( title: "Geofence Error", message: "Punch from Wrong Location.", okBtnString: "Ok", ); } else if (event == GeofenceEvent.enter) { _geofenceSubscription?.cancel(); Geofence.stopGeofenceService(); locationPunch2(); } }); }
额外优化建议
- 避免用
event.toString()判断事件类型,直接通过枚举常量比较(如event == GeofenceEvent.exit),减少字符串匹配的潜在问题。 - 页面销毁或不再需要地理围栏功能时,记得调用
_geofenceSubscription?.cancel()和Geofence.stopGeofenceService(),防止内存泄漏。
内容的提问来源于stack exchange,提问作者Honey Last
相关产品推荐
相关产品推荐

