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

flutter_map判断缩放显示标记触发LateInitializationError问题

问题修复:Flutter Map缩放控制标记显示的LateInitializationError

错误原因

直接在build方法中访问_mapController.zoom时,MapController的内部状态还未与FlutterMap组件完成绑定初始化,导致读取到未初始化的_state字段,触发LateInitializationError。

正确修复方案

方案1:通过MapOptions的缩放回调维护状态变量

在State类中维护一个本地缩放状态变量,利用MapOptions.onZoomChanged回调实时更新该变量,以此控制标记层的显示:

class OnTapPage extends StatefulWidget {
  static const String route = 'on_tap';
  const OnTapPage({Key? key}) : super(key: key);
  @override
  OnTapPageState createState() => OnTapPageState();
}

class OnTapPageState extends State<OnTapPage> {
  static LatLng london = LatLng(51.5, -0.09);
  late MapController _mapController;
  double _currentZoom = 5; // 初始化为地图默认缩放值

  @override
  void initState() {
    super.initState();
    _mapController = MapController();
  }

  @override
  Widget build(BuildContext context) {
    final markers = <Marker>[
      Marker(
        width: 80,
        height: 80,
        point: london,
        builder: (ctx) => GestureDetector(
          onTap: () {
            ScaffoldMessenger.of(ctx).showSnackBar(const SnackBar(
              content: Text('Tapped on blue FlutterLogo Marker'),
            ));
          },
          child: const FlutterLogo(),
        ),
      ),
    ];

    return Scaffold(
      appBar: AppBar(title: const Text('OnTap')),
      body: Padding(
        padding: const EdgeInsets.all(8),
        child: Column(
          children: [
            Flexible(
              child: FlutterMap(
                mapController: _mapController,
                options: MapOptions(
                  center: london,
                  zoom: _currentZoom,
                  maxZoom: 15, // 注意:原代码maxZoom设为5,永远达不到9,这里需要调整
                  minZoom: 3,
                  onZoomChanged: (newZoom) {
                    setState(() => _currentZoom = newZoom);
                  },
                ),
                children: [
                  TileLayer(
                    urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                    userAgentPackageName: 'dev.fleaflet.flutter_map.example',
                  ),
                  if (_currentZoom > 9) MarkerLayer(markers: markers),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

方案2:给MapController添加监听器

通过给MapController添加监听器,监听缩放变化并更新本地状态:

class OnTapPage extends StatefulWidget {
  static const String route = 'on_tap';
  const OnTapPage({Key? key}) : super(key: key);
  @override
  OnTapPageState createState() => OnTapPageState();
}

class OnTapPageState extends State<OnTapPage> {
  static LatLng london = LatLng(51.5, -0.09);
  late MapController _mapController;
  double _currentZoom = 5;

  @override
  void initState() {
    super.initState();
    _mapController = MapController();
    // 添加缩放监听器
    _mapController.addListener(_onMapChanged);
  }

  void _onMapChanged() {
    if (_mapController.zoom != _currentZoom) {
      setState(() => _currentZoom = _mapController.zoom);
    }
  }

  @override
  void dispose() {
    // 移除监听器,避免内存泄漏
    _mapController.removeListener(_onMapChanged);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final markers = <Marker>[
      Marker(
        width: 80,
        height: 80,
        point: london,
        builder: (ctx) => GestureDetector(
          onTap: () {
            ScaffoldMessenger.of(ctx).showSnackBar(const SnackBar(
              content: Text('Tapped on blue FlutterLogo Marker'),
            ));
          },
          child: const FlutterLogo(),
        ),
      ),
    ];

    return Scaffold(
      appBar: AppBar(title: const Text('OnTap')),
      body: Padding(
        padding: const EdgeInsets.all(8),
        child: Column(
          children: [
            Flexible(
              child: FlutterMap(
                mapController: _mapController,
                options: MapOptions(
                  center: london,
                  zoom: _currentZoom,
                  maxZoom: 15, // 调整maxZoom使其能达到9以上
                  minZoom: 3,
                ),
                children: [
                  TileLayer(
                    urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                    userAgentPackageName: 'dev.fleaflet.flutter_map.example',
                  ),
                  if (_currentZoom > 9) MarkerLayer(markers: markers),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

额外注意

原代码中MapOptions.maxZoom设为5,永远无法达到9以上的缩放级别,所以需要调整这个值才能看到标记显示效果。

内容的提问来源于stack exchange,提问作者Pannam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:23:15