Flutter开发遇LateInitializationError: 'initialPosition'未初始化如何解决
报错原因
getUserLocation是异步方法,执行需要耗时,在地图页面首次触发build时,initialPosition还没完成初始化就被强制解包使用- ViewModel中的
lastMapPosition直接通过initialPosition!赋值,此时initialPosition还不存在有效值,也会触发Late初始化错误 - 用
late修饰可空类型LatLng?本身逻辑冲突:late的作用是承诺变量为非空、后续会完成初始化,和可空标识的语义矛盾
修复步骤
第一步:修改ViewModel代码
调整变量定义逻辑,移除不必要的late修饰,处理空值场景:
class MapViewModel extends BaseViewModel { // 去掉late修饰,默认赋值为null LatLng? initialPosition; // 先给一个兜底默认坐标,等定位完成后再更新 LatLng lastMapPosition = const LatLng(39.9042, 116.4074); void getUserLocation() async { Position position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.high); List<Placemark> placemarks = await placemarkFromCoordinates( position.latitude, position.longitude); initialPosition = LatLng(position.latitude, position.longitude); // 拿到定位结果后再更新lastMapPosition lastMapPosition = initialPosition!; print('${placemarks[0].name}'); setState(ViewState.Idle); } }
第二步:修改地图页面代码,增加加载状态判断
build时先校验initialPosition是否有有效值,无值时显示加载占位,禁止直接强制解包:
class MapScreen extends StatelessWidget { @override Widget build(BuildContext context) { return BaseScreen<MapViewModel>( onFinish: (_) { }, onModelReady: (mapViewModel) { mapViewModel.getUserLocation(); }, builder: (context, mapViewModel, child){ // 空值判断,未拿到定位时显示加载进度 if (mapViewModel.initialPosition == null) { return const Center(child: CircularProgressIndicator()); } return GoogleMap( initialCameraPosition: CameraPosition( target: mapViewModel.initialPosition!, ), myLocationEnabled: true, ); }, ); } }
额外优化建议
- 可以给
getUserLocation增加异常捕获逻辑,处理定位权限被拒、定位失败的场景,避免出现无响应的加载状态 - 如果业务不允许使用默认兜底坐标,可以在未拿到用户定位前,先弹出定位权限申请提示
内容的提问来源于stack exchange,提问作者Mahmoud Al-Haroon
相关产品推荐
相关产品推荐

