Flutter构建MapScreen抛出LateInitializationError: _origin未初始化
报错原因
- 核心问题是
late关键字的误用:你给_origin、_destination、_info、_googleMapController四个字段加了late修饰,相当于向Dart运行时承诺这些字段会在第一次被访问前完成非空赋值,但组件首次执行build渲染时,这些字段还没有被赋值就被读取判断,直接触发LateInitializationError。 - 伴生的逻辑错误有两个:一是
late修饰的非空字段在未初始化时,直接做!= null判断本身就会抛错,根本走不到你写的空判断分支;二是_addMarker方法里添加终点标记时,错误给_origin字段赋值,会导致起点标记被覆盖,还有重置值时用动态null给非空late字段赋值,本身就不符合类型要求。
修复步骤
- 调整字段声明,把允许为空的字段从
late非空类型改成可空类型,同时调整dispose方法的空安全调用:
class _MapScreenState extends State<MapScreen> { static const _initialCameraPosition = CameraPosition( target: LatLng(-1.286389, 36.817223), zoom: 11.5, ); // 去掉late,改为可空类型 GoogleMapController? _googleMapController; Marker? _origin; Marker? _destination; Directions? _info; @override void dispose() { // 加空安全调用,避免控制器未初始化时调用dispose报错 _googleMapController?.dispose(); super.dispose(); }
- 修复AppBar上两个定位按钮的点击逻辑,增加空判断,避免字段为null时执行动画报错:
// ORIGIN按钮修改后 TextButton( onPressed: () { // 字段为空时直接返回,不执行后续逻辑 if (_origin == null || _googleMapController == null) return; _googleMapController!.animateCamera( CameraUpdate.newCameraPosition( CameraPosition( target: _origin!.position, zoom: 14.5, tilt: 50.0, ), ), ); }, style: TextButton.styleFrom( primary: Colors.green, textStyle: const TextStyle(fontWeight: FontWeight.w600), ), child: const Text('ORIGIN'), ), // DEST按钮修改后 TextButton( onPressed: () { if (_destination == null || _googleMapController == null) return; _googleMapController!.animateCamera( CameraUpdate.newCameraPosition( CameraPosition( target: _destination!.position, zoom: 14.5, tilt: 50.0), ), ); }, style: TextButton.styleFrom( primary: Colors.blue, textStyle: const TextStyle(fontWeight: FontWeight.w600), ), child: const Text('DEST'), ),
- 修复
_addMarker方法里的赋值错误,去掉多余的临时变量,直接给可空字段赋值null即可:
Future<void> _addMarker(LatLng pos) async { if (_origin == null || (_origin != null && _destination != null)) { setState(() { _origin = Marker( markerId: const MarkerId('origin'), infoWindow: const InfoWindow(title: 'origin'), icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen), position: pos, ); // 直接重置为null即可 _destination = null; _info = null; }); } else { setState(() { // 修复原代码错误:这里应该给_destination赋值,不是_origin _destination = Marker( markerId: const MarkerId('destination'), infoWindow: const InfoWindow(title: 'destination'), icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue), position: pos, ); }); final directions = await DirectionsRepository() .getDirections(origin: _origin!.position, destination: pos); setState(() => _info = directions); } }
- 修复浮动定位按钮的点击逻辑,增加空判断:
floatingActionButton: FloatingActionButton( backgroundColor: Theme.of(context).primaryColor, foregroundColor: Colors.black, onPressed: () { if (_googleMapController == null) return; _googleMapController!.animateCamera( _info != null ? CameraUpdate.newLatLngBounds(_info!.bounds, 100.0) : CameraUpdate.newCameraPosition(_initialCameraPosition), ); }, child: const Icon(Icons.center_focus_strong), ),
说明:GoogleMap组件内原有的
if (_origin != null)、if (_destination != null)、if (_info != null)判断不需要修改,字段改为可空类型后默认值就是null,这些判断可以正常执行,不会再触发初始化错误。
内容的提问来源于stack exchange,提问作者Muema
相关产品推荐
相关产品推荐

