Android Studio模拟器中Flutter Geolocator PositionStream停止工作
截至昨日,Geolocator的positionStream运行正常,但目前即使通过模拟器扩展控件修改设备位置,该流也不再输出任何数据,且无错误日志。相关代码如下:
相关代码片段
Riverpod位置流Provider
@riverpod Stream<Position> positionStream( PositionStreamRef ref, ) async* { final locationService = ref.watch(locationServiceProvider); yield* locationService.geolocator.getPositionStream( locationSettings: locationService.getLocationSettings(), ); }
位置服务中的设置方法
LocationSettings getLocationSettings() { if (defaultTargetPlatform == TargetPlatform.android) { return AndroidSettings( distanceFilter: 50, //(Optional) Set foreground notification config to keep the app alive //when going to the background foregroundNotificationConfig: const ForegroundNotificationConfig( notificationTitle: "Running in Background", notificationText: "Example app will continue to receive your location even when you aren't using it", notificationIcon: AndroidResource(name: 'notification_icon'), )); } else if (defaultTargetPlatform == TargetPlatform.iOS) { return AppleSettings( accuracy: LocationAccuracy.best, distanceFilter: AppLocationSettings.locationChangeDistance, activityType: ActivityType.automotiveNavigation, pauseLocationUpdatesAutomatically: true, // Only set to true if our app will be started up in the background. showBackgroundLocationIndicator: true, ); } else { return const LocationSettings( accuracy: LocationAccuracy.best, distanceFilter: 50, ); } }
用于监听positionStreamProvider的Provider
@riverpod CameraPosition myLocationCameraPosition(MyLocationCameraPositionRef ref) { final myLocation = ref.watch(positionStreamProvider.select((value) => value.valueOrNull)); return CameraPosition( target: LatLng( myLocation?.latitude ?? defaultLatLng.latitude, myLocation?.longitude ?? defaultLatLng.longitude, ), zoom: defaultMapZoom, ); }
Provider启动方式
final locationAsync = ref.watch( positionStreamProvider.select((value) => value.whenData((value) => true)), );
排查与修复步骤
检查位置权限状态
确认应用已授予精确位置权限(Android)或使用期间/始终允许权限(iOS),调用Geolocator.checkPermission()验证权限,若被拒绝需引导用户重新授权。调整位置更新阈值
Android设置中distanceFilter设为50米,模拟器位置修改可能未达到该距离差,临时改为0测试:distanceFilter: 0,iOS端的
AppLocationSettings.locationChangeDistance也需确认数值是否过大,建议临时改为0。修复Riverpod流生命周期问题
当前Provider使用async*直接转发流,若locationServiceProvider重建可能导致流中断,修改为持有流并保持Provider活跃:@riverpod Stream<Position> positionStream(PositionStreamRef ref) { final locationService = ref.watch(locationServiceProvider); final stream = locationService.geolocator.getPositionStream( locationSettings: locationService.getLocationSettings(), ); ref.keepAlive(); return stream; }验证流的订阅状态
在流中添加日志,确认是否有数据输出:@riverpod Stream<Position> positionStream(PositionStreamRef ref) { final locationService = ref.watch(locationServiceProvider); final stream = locationService.geolocator.getPositionStream( locationSettings: locationService.getLocationSettings(), ).map((position) { print('Received position: ${position.latitude}, ${position.longitude}'); return position; }); ref.keepAlive(); return stream; }通过控制台日志判断是流未产生数据还是订阅未生效。
检查模拟器位置模拟方式
Android模拟器:使用Extended Controls > Location,确保点击“Set location”而非仅修改经纬度;iOS模拟器:通过Debug > Location选择自定义位置,或用simctl命令行设置位置。重置Geolocator实例
在LocationService中添加重置方法,避免内部状态异常:void resetGeolocator() { _geolocator = GeolocatorPlatform.instance; }在Provider中监听重置信号,触发流重建。
内容的提问来源于stack exchange,提问作者DeKekem

