Flutter:非StatefulWidget类中如何初始化定位变量?
解决LocationTrack类中latitude/longitude未初始化及LatLng不接受null的问题
方案1:给坐标设置默认初始值
直接给latitude和longitude赋值默认坐标(比如0.0),避免使用late关键字导致未初始化错误。当位置流首次返回数据时,会自动覆盖默认值。
class LocationTrack { double latitude = 0.0; double longitude = 0.0; late LocationSettings locationSettings; StreamSubscription<Position> getTrackingLocation() { // 原平台判断及locationSettings初始化代码不变 if (defaultTargetPlatform == TargetPlatform.android) { locationSettings = AndroidSettings( accuracy: LocationAccuracy.high, distanceFilter: 10, forceLocationManager: true, intervalDuration: const Duration(seconds: 10), foregroundNotificationConfig: const ForegroundNotificationConfig( notificationText: "Example app will continue to receive your location even when you aren't using it", notificationTitle: "Running in Background", enableWakeLock: true, )); } else if (defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS) { locationSettings = AppleSettings( accuracy: LocationAccuracy.high, activityType: ActivityType.fitness, distanceFilter: 10, pauseLocationUpdatesAutomatically: true, showBackgroundLocationIndicator: false, ); } else { locationSettings = const LocationSettings( accuracy: LocationAccuracy.high, distanceFilter: 10, ); } return Geolocator.getPositionStream(locationSettings: locationSettings) .listen((Position position) { latitude = position.latitude; longitude = position.longitude; }); } }
注意:如果不想显示初始的0.0, 0.0坐标,可在UI层添加判断,比如当坐标未更新时隐藏标记或显示加载状态。
方案2:先获取初始位置再启动监听
通过Geolocator.getCurrentPosition()先获取一次当前位置,初始化latitude和longitude,再启动位置流监听,确保变量在被访问前已赋值有效坐标。
class LocationTrack { late double latitude; late double longitude; late LocationSettings locationSettings; // 初始化初始位置 Future<void> initInitialLocation() async { // 需提前处理定位权限 Position initialPos = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.high, ); latitude = initialPos.latitude; longitude = initialPos.longitude; } StreamSubscription<Position> getTrackingLocation() { // 原平台判断及locationSettings初始化代码不变 if (defaultTargetPlatform == TargetPlatform.android) { locationSettings = AndroidSettings(/* 原配置 */); } else if (defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS) { locationSettings = AppleSettings(/* 原配置 */); } else { locationSettings = const LocationSettings(/* 原配置 */); } return Geolocator.getPositionStream(locationSettings: locationSettings) .listen((Position position) { latitude = position.latitude; longitude = position.longitude; }); } }
使用方式:在full_screen_map中先调用初始化方法,再启动监听:
final locationTrack = LocationTrack(); // 处理权限后调用 await locationTrack.initInitialLocation(); locationTrack.getTrackingLocation(); // 之后可安全访问latitude和longitude
方案3:用StreamController暴露位置流(推荐)
不再直接暴露类内的latitude和longitude,而是通过StreamController将位置转换为LatLng流,UI层直接监听流更新标记。这种方式彻底避免变量未初始化问题,同时解耦数据层与UI层。
import 'package:latlong2/latlong.dart'; // 根据你的latlng包调整 class LocationTrack { late LocationSettings locationSettings; final _locationStreamController = StreamController<LatLng>.broadcast(); // 对外暴露位置流 Stream<LatLng> get locationStream => _locationStreamController.stream; StreamSubscription<Position> startTracking() { // 原平台判断及locationSettings初始化代码不变 if (defaultTargetPlatform == TargetPlatform.android) { locationSettings = AndroidSettings(/* 原配置 */); } else if (defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS) { locationSettings = AppleSettings(/* 原配置 */); } else { locationSettings = const LocationSettings(/* 原配置 */); } return Geolocator.getPositionStream(locationSettings: locationSettings) .listen((Position position) { final latLng = LatLng(position.latitude, position.longitude); _locationStreamController.add(latLng); }); } // 记得释放资源 void dispose() { _locationStreamController.close(); } }
使用方式:在full_screen_map中监听流更新UI:
final locationTrack = LocationTrack(); late StreamSubscription<LatLng> _locationSub; @override void initState() { super.initState(); _locationSub = locationTrack.locationStream.listen((LatLng latLng) { setState(() { // 更新标记位置 currentMarker = Marker(position: latLng); }); }); locationTrack.startTracking(); } @override void dispose() { _locationSub.cancel(); locationTrack.dispose(); super.dispose(); }
内容的提问来源于stack exchange,提问作者santosvision
相关产品推荐
相关产品推荐

