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
相关产品推荐
相关产品推荐

