Flutter实现地图启动加载用户位置为何首次获取currentPosition为null
问题原因
getCurrentPosition是异步方法,initState中调用它之后不会等待定位请求返回就会继续执行组件渲染逻辑。首次触发build方法时,定位还没有完成,currentPosition仍是初始的null值,你直接对currentPosition使用!强制非空断言,就触发了「Null check operator used on a null value」报错。- 等定位请求执行完成,调用
setState更新状态后,currentPosition已经被赋值为有效坐标,组件重新渲染时不再为空,报错就会自动消失,地图正常加载。
补充:你代码中对
position != null的判断是多余的,Geolocator.getCurrentPosition方法的返回值是不可空的Position类型,只要方法没有抛出异常就不会返回null。
修复方案
推荐在定位完成前展示加载占位,避免直接渲染需要非空位置参数的GoogleMap组件,修改逻辑如下:
- 新增加载状态标识
class _UsermapState extends State<Usermap> { LatLng? currentPosition; final Completer<GoogleMapController> _controller = Completer(); Set<Marker> markers = {}; // 新增加载状态 bool _isLocating = true; // ...原有其他代码 }
- 完善定位逻辑更新加载状态,建议额外增加权限判断避免崩溃
Future getCurrentPosition() async { // 定位权限校验 bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { _isLocating = false; setState(() {}); return; } LocationPermission permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { _isLocating = false; setState(() {}); return; } } if (permission == LocationPermission.deniedForever) { _isLocating = false; setState(() {}); return; } // 获取定位 Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); setState(() { currentPosition = LatLng(position.latitude, position.longitude); markers.add(Marker( markerId: const MarkerId('12'), position: currentPosition!, infoWindow: const InfoWindow(title: 'am here') )); _isLocating = false; }); }
- 修改build方法,定位中展示加载占位
@override Widget build(BuildContext context) { final height = MediaQuery.of(context).size.height; final width = MediaQuery.of(context).size.width; return SizedBox( height: height, width: width, child: Scaffold( body: _isLocating ? const Center(child: CircularProgressIndicator()) : Stack( children: [ GoogleMap( initialCameraPosition: CameraPosition(target: currentPosition!, zoom: 15), myLocationEnabled: true, myLocationButtonEnabled: false, mapType: MapType.normal, zoomControlsEnabled: false, zoomGesturesEnabled: true, markers: markers, onMapCreated: (GoogleMapController controller) { _controller.complete(controller); }, ), // 原有缩放按钮、定位按钮等组件保持不变 ], ), ), ); }
如果你不想展示加载占位,也可以给initialCameraPosition先设置一个默认的公共坐标,等定位拿到后再调用地图控制器的animateCamera方法移动到用户当前位置,同样可以避免空值报错。
内容的提问来源于stack exchange,提问作者kajembe
相关产品推荐
相关产品推荐

