You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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组件,修改逻辑如下:

  1. 新增加载状态标识
class _UsermapState extends State<Usermap> {
  LatLng? currentPosition;
  final Completer<GoogleMapController> _controller = Completer();
  Set<Marker> markers = {};
  // 新增加载状态
  bool _isLocating = true;
  // ...原有其他代码
}
  1. 完善定位逻辑更新加载状态,建议额外增加权限判断避免崩溃
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;
  });
}
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 20:45:05